/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved.
 */

#include "hellovk.h"
#include "fif.h"
#include <set>
#include <unordered_set>
#include <log.hpp>
#include <AAssetImporter.h>
#include <DescriptorPool.h>
#include <CommandPool.h>
#include <Utils.h>
#include <cstdio>
#include <cstring>

bool vkt::HelloVK::ENABLE_EXTRAPOLATION = false;
namespace vkt {
namespace {
// 静态标志，用于控制高频操作的日志输出
static bool s_loggedWaitForFences = false;
static bool s_loggedResetFences = false;
static bool s_loggedResetCommandPool = false;
static bool s_loggedAcquireNextImage = false;
static bool s_loggedBeginCommandBuffer = false;
static bool s_loggedEndCommandBuffer = false;
static bool s_loggedQueueSubmit = false;
static bool s_loggedQueuePresent = false;

// 绘制API测试标志
static bool s_loggedCmdDrawIndexed = false;
static bool s_loggedCmdDrawIndexedIndirect = false;
static bool s_loggedCmdDrawIndexedIndirectCount = false;
static bool s_loggedCmdDrawIndirect = false;
static bool s_loggedCmdDrawIndirectCount = false;

[[nodiscard]] const char *ToStringMessageSeverity(VkDebugUtilsMessageSeverityFlagBitsEXT s)
{
    switch (s) {
        case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT:
            return "VERBOSE";
        case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT:
            return "ERROR";
        case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT:
            return "WARNING";
        case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT:
            return "INFO";
        default:
            return "UNKNOWN";
    }
}

[[nodiscard]] const char *ToStringMessageType(VkDebugUtilsMessageTypeFlagsEXT s)
{
    if (s == (VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
        VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT)) {
        return "General | Validation | Performance";
    }

    if (s == (VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT)) {
        return "Validation | Performance";
    }

    if (s == (VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT)) {
        return "General | Performance";
    }

    if (s == (VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT)) {
        return "Performance";
    }

    if (s == (VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT)) {
        return "General | Validation";
    }

    if (s == VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT) {
        return "Validation";
    }

    if (s == VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT) {
        return "General";
    }

    return "Unknown";
}

VKAPI_ATTR VkBool32 VKAPI_CALL DebugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
    VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData,
    void * /* pUserData */)
{
    static std::unordered_set<uint32_t> const validationFilter{ // Unspecified message. Safe to ignore it.
        0x00000000U, 0x675DC32EU
    };

    auto const messageID = static_cast<uint32_t>(pCallbackData->messageIdNumber);
    if (validationFilter.contains(messageID)) {
        return VK_FALSE;
    }

    auto ms = ToStringMessageSeverity(messageSeverity);
    auto mt = ToStringMessageType(messageType);
    GOLOGI("[%s: %s]\n%s\n", ms, mt, pCallbackData->pMessage);

    return VK_FALSE;
}

void PopulateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT &createInfo)
{
    constexpr static VkValidationFeatureEnableEXT const validationFeatures[] = {
        VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT,
        VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT
    };

    constexpr static VkValidationFeaturesEXT validationInfo {
        .sType = VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT,
        .pNext = nullptr,
        .enabledValidationFeatureCount = static_cast<uint32_t>(std::size(validationFeatures)),
        .pEnabledValidationFeatures = validationFeatures,
        .disabledValidationFeatureCount = 0U,
        .pDisabledValidationFeatures = nullptr
    };

    createInfo = {};
    createInfo.pNext = &validationInfo;
    createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;

    createInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT |
        VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;

    createInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
        VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;

    createInfo.pfnUserCallback = &DebugCallback;
}


glm::mat4 ConvertGLMMat4ToMat4(glm::mat4 matrix)
{
    // 直接返回glm矩阵，不再需要转换
    return matrix;
}

/**
 * GetPrerotationMatrix handles screen rotation with 3 hardcoded rotation
 * matrices (detailed below). We skip the 180 degrees rotation.
 */
void GetPrerotationMatrix(const VkSurfaceCapabilitiesKHR &capabilities,
    const VkSurfaceTransformFlagBitsKHR &pretransformFlag, std::array<float, 16> &mat)
{
    // mat is initialized to the identity matrix
    mat = { 1., 0., 0., 0., 0., 1., 0., 0., 0., 0., 1., 0., 0., 0., 0., 1. };
    if (pretransformFlag & VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR) {
        // mat is set to a 90 deg rotation matrix
        mat = { 0., 1., 0., 0., -1., 0, 0., 0., 0., 0., 1., 0., 0., 0., 0., 1. };
        return;
    }

    if (pretransformFlag & VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR) {
        // mat is set to 270 deg rotation matrix
        mat = { 0., -1., 0., 0., 1., 0, 0., 0., 0., 0., 1., 0., 0., 0., 0., 1. };
    }
}
} // end of anonymous namespace

void HelloVK::InitVulkan()
{
    CreateInstance();
    CreateSurface();
    PickPhysicalDevice();
    CreateLogicalDeviceAndQueue();
    SetupDebugMessenger();
    EstablishDisplaySizeIdentity();
    CreateSwapChain();
    CreateImageViews();
    FGInitDevice();
    FGCreateCommandPool();
    FGCreateColorResources();
    FGCreateDepthResources();
    OHTestApp::DescriptorPool::Instance().Init();
    FGCreateSwapchainSyncObjects();
    FGInitUIRenderer();
    FGInitMainSceneRenderer();

    // 运行一次 API 冒烟测试
    RunApiSmokeTestsOnce();

    m_initialized = true;
}

void HelloVK::RunApiSmokeTestsOnce()
{
    static bool s_testRan = false;
    if (s_testRan) return;
    s_testRan = true;

    VkDevice device = m_device;
    
    // ==================== Test: vkCmdResetQueryPool ====================
    {
        VkQueryPoolCreateInfo queryPoolInfo{
            VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,
            nullptr,
            0,
            VK_QUERY_TYPE_OCCLUSION,
            2,
            0
        };
        
        VkQueryPool queryPool = VK_NULL_HANDLE;
        VkResult result = vkCreateQueryPool(device, &queryPoolInfo, nullptr, &queryPool);
        if (result == VK_SUCCESS) {
            VkCommandPoolCreateInfo cmdPoolInfo{VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, nullptr, 0, OHTestApp::Device::Instance().GetQueueFamilyIndex()};
            VkCommandPool tempCmdPool = VK_NULL_HANDLE;
            result = vkCreateCommandPool(device, &cmdPoolInfo, nullptr, &tempCmdPool);
            
            if (result == VK_SUCCESS) {
                VkCommandBufferAllocateInfo cmdBufferInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, nullptr, tempCmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1};
                VkCommandBuffer tempCmdBuffer = VK_NULL_HANDLE;
                result = vkAllocateCommandBuffers(device, &cmdBufferInfo, &tempCmdBuffer);
                
                if (result == VK_SUCCESS) {
                    VkCommandBufferBeginInfo beginInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, nullptr};
                    result = vkBeginCommandBuffer(tempCmdBuffer, &beginInfo);
                    
                    if (result == VK_SUCCESS) {
                        vkCmdResetQueryPool(tempCmdBuffer, queryPool, 0, 2);
                        GOLOGW("vkCmdResetQueryPool completed successfully");
                        vkEndCommandBuffer(tempCmdBuffer);
                    }
                }
                vkDestroyCommandPool(device, tempCmdPool, nullptr);
            }
            vkDestroyQueryPool(device, queryPool, nullptr);
        } else {
            GOLOGE("vkCmdResetQueryPool failed with error: %d", result);
        }
    }
    
    // ==================== Test: vkCmdResolveImage ====================
    {
        VkImageCreateInfo srcImageInfo{
            VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, nullptr, 0,
            VK_IMAGE_TYPE_2D, VK_FORMAT_R8G8B8A8_UNORM,
            {256, 256, 1}, 1, 1,
            VK_SAMPLE_COUNT_4_BIT,
            VK_IMAGE_TILING_OPTIMAL,
            VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
            VK_SHARING_MODE_EXCLUSIVE, 0, nullptr,
            VK_IMAGE_LAYOUT_UNDEFINED
        };
        
        VkImage srcImage = VK_NULL_HANDLE;
        VkResult result = vkCreateImage(device, &srcImageInfo, nullptr, &srcImage);
        if (result == VK_SUCCESS) {
            VkImageCreateInfo dstImageInfo = srcImageInfo;
            dstImageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
            dstImageInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT;
            
            VkImage dstImage = VK_NULL_HANDLE;
            result = vkCreateImage(device, &dstImageInfo, nullptr, &dstImage);
            if (result == VK_SUCCESS) {
                VkCommandPoolCreateInfo cmdPoolInfo{VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, nullptr, 0, OHTestApp::Device::Instance().GetQueueFamilyIndex()};
                VkCommandPool tempCmdPool = VK_NULL_HANDLE;
                result = vkCreateCommandPool(device, &cmdPoolInfo, nullptr, &tempCmdPool);
                
                if (result == VK_SUCCESS) {
                    VkCommandBufferAllocateInfo cmdBufferInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, nullptr, tempCmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1};
                    VkCommandBuffer tempCmdBuffer = VK_NULL_HANDLE;
                    result = vkAllocateCommandBuffers(device, &cmdBufferInfo, &tempCmdBuffer);
                    
                    if (result == VK_SUCCESS) {
                        VkCommandBufferBeginInfo beginInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, nullptr};
                        result = vkBeginCommandBuffer(tempCmdBuffer, &beginInfo);
                        
                        if (result == VK_SUCCESS) {
                            VkImageResolve resolveRegion{
                                {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1},
                                {0, 0, 0},
                                {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1},
                                {0, 0, 0},
                                {256, 256, 1}
                            };
                            
                            vkCmdResolveImage(tempCmdBuffer, srcImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
                                            dstImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &resolveRegion);
                            
                            GOLOGW("vkCmdResolveImage completed successfully");
                            vkEndCommandBuffer(tempCmdBuffer);
                        }
                    }
                    vkDestroyCommandPool(device, tempCmdPool, nullptr);
                }
                vkDestroyImage(device, dstImage, nullptr);
            }
            vkDestroyImage(device, srcImage, nullptr);
        } else {
            GOLOGE("vkCmdResolveImage failed with error: %d", result);
        }
    }
    
    // ==================== Test: vkCmdSetBlendConstants ====================
    {
        VkCommandPoolCreateInfo cmdPoolInfo{VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, nullptr, 0, OHTestApp::Device::Instance().GetQueueFamilyIndex()};
        VkCommandPool tempCmdPool = VK_NULL_HANDLE;
        VkResult result = vkCreateCommandPool(device, &cmdPoolInfo, nullptr, &tempCmdPool);
        
        if (result == VK_SUCCESS) {
            VkCommandBufferAllocateInfo cmdBufferInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, nullptr, tempCmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1};
            VkCommandBuffer tempCmdBuffer = VK_NULL_HANDLE;
            result = vkAllocateCommandBuffers(device, &cmdBufferInfo, &tempCmdBuffer);
            
            if (result == VK_SUCCESS) {
                VkCommandBufferBeginInfo beginInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, nullptr};
                result = vkBeginCommandBuffer(tempCmdBuffer, &beginInfo);
                
                if (result == VK_SUCCESS) {
                    float blendConstants[4] = {0.5f, 0.5f, 0.5f, 1.0f};
                    vkCmdSetBlendConstants(tempCmdBuffer, blendConstants);
                    GOLOGW("vkCmdSetBlendConstants completed successfully");
                    vkEndCommandBuffer(tempCmdBuffer);
                }
            }
            vkDestroyCommandPool(device, tempCmdPool, nullptr);
        } else {
            GOLOGE("vkCmdSetBlendConstants failed with error: %d", result);
        }
    }
    
    // ==================== Test: vkCmdSetCullMode ====================
    {
        PFN_vkCmdSetCullMode pfnCmdSetCullMode = 
            reinterpret_cast<PFN_vkCmdSetCullMode>(vkGetDeviceProcAddr(device, "vkCmdSetCullMode"));
        
        if (pfnCmdSetCullMode == nullptr) {
            GOLOGE("vkCmdSetCullMode failed with error: function not available in driver");
        } else {
            VkCommandPoolCreateInfo cmdPoolInfo{VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, nullptr, 0, OHTestApp::Device::Instance().GetQueueFamilyIndex()};
            VkCommandPool tempCmdPool = VK_NULL_HANDLE;
            VkResult result = vkCreateCommandPool(device, &cmdPoolInfo, nullptr, &tempCmdPool);
            
            if (result == VK_SUCCESS) {
                VkCommandBufferAllocateInfo cmdBufferInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, nullptr, tempCmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1};
                VkCommandBuffer tempCmdBuffer = VK_NULL_HANDLE;
                result = vkAllocateCommandBuffers(device, &cmdBufferInfo, &tempCmdBuffer);
                
                if (result == VK_SUCCESS) {
                    VkCommandBufferBeginInfo beginInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, nullptr};
                    result = vkBeginCommandBuffer(tempCmdBuffer, &beginInfo);
                    
                    if (result == VK_SUCCESS) {
                        pfnCmdSetCullMode(tempCmdBuffer, VK_CULL_MODE_BACK_BIT);
                        GOLOGW("vkCmdSetCullMode completed successfully");
                        vkEndCommandBuffer(tempCmdBuffer);
                    }
                }
                vkDestroyCommandPool(device, tempCmdPool, nullptr);
            } else {
                GOLOGE("vkCmdSetCullMode failed with error: %d", result);
            }
        }
    }
    
    // ==================== Test: vkCmdSetDepthBias ====================
    {
        VkCommandPoolCreateInfo cmdPoolInfo{VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, nullptr, 0, OHTestApp::Device::Instance().GetQueueFamilyIndex()};
        VkCommandPool tempCmdPool = VK_NULL_HANDLE;
        VkResult result = vkCreateCommandPool(device, &cmdPoolInfo, nullptr, &tempCmdPool);
        
        if (result == VK_SUCCESS) {
            VkCommandBufferAllocateInfo cmdBufferInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, nullptr, tempCmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1};
            VkCommandBuffer tempCmdBuffer = VK_NULL_HANDLE;
            result = vkAllocateCommandBuffers(device, &cmdBufferInfo, &tempCmdBuffer);
            
            if (result == VK_SUCCESS) {
                VkCommandBufferBeginInfo beginInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, nullptr};
                result = vkBeginCommandBuffer(tempCmdBuffer, &beginInfo);
                
                if (result == VK_SUCCESS) {
                    vkCmdSetDepthBias(tempCmdBuffer, 1.0f, 0.0f, 1.0f);
                    GOLOGW("vkCmdSetDepthBias completed successfully");
                    vkEndCommandBuffer(tempCmdBuffer);
                }
            }
            vkDestroyCommandPool(device, tempCmdPool, nullptr);
        } else {
            GOLOGE("vkCmdSetDepthBias failed with error: %d", result);
        }
    }
    
    // ==================== Test: vkCmdSetDepthBiasEnable ====================
    {
        PFN_vkCmdSetDepthBiasEnable pfnCmdSetDepthBiasEnable = 
            reinterpret_cast<PFN_vkCmdSetDepthBiasEnable>(vkGetDeviceProcAddr(device, "vkCmdSetDepthBiasEnable"));
        
        if (pfnCmdSetDepthBiasEnable == nullptr) {
            GOLOGE("vkCmdSetDepthBiasEnable failed with error: function not available in driver");
        } else {
            VkCommandPoolCreateInfo cmdPoolInfo{VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, nullptr, 0, OHTestApp::Device::Instance().GetQueueFamilyIndex()};
            VkCommandPool tempCmdPool = VK_NULL_HANDLE;
            VkResult result = vkCreateCommandPool(device, &cmdPoolInfo, nullptr, &tempCmdPool);
            
            if (result == VK_SUCCESS) {
                VkCommandBufferAllocateInfo cmdBufferInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, nullptr, tempCmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1};
                VkCommandBuffer tempCmdBuffer = VK_NULL_HANDLE;
                result = vkAllocateCommandBuffers(device, &cmdBufferInfo, &tempCmdBuffer);
                
                if (result == VK_SUCCESS) {
                    VkCommandBufferBeginInfo beginInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, nullptr};
                    result = vkBeginCommandBuffer(tempCmdBuffer, &beginInfo);
                    
                    if (result == VK_SUCCESS) {
                        pfnCmdSetDepthBiasEnable(tempCmdBuffer, VK_TRUE);
                        GOLOGW("vkCmdSetDepthBiasEnable completed successfully");
                        vkEndCommandBuffer(tempCmdBuffer);
                    }
                }
                vkDestroyCommandPool(device, tempCmdPool, nullptr);
            } else {
                GOLOGE("vkCmdSetDepthBiasEnable failed with error: %d", result);
            }
        }
    }
    
    // ==================== Test: vkCmdSetDepthBounds ====================
    {
        VkCommandPoolCreateInfo cmdPoolInfo{VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, nullptr, 0, OHTestApp::Device::Instance().GetQueueFamilyIndex()};
        VkCommandPool tempCmdPool = VK_NULL_HANDLE;
        VkResult result = vkCreateCommandPool(device, &cmdPoolInfo, nullptr, &tempCmdPool);
        
        if (result == VK_SUCCESS) {
            VkCommandBufferAllocateInfo cmdBufferInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, nullptr, tempCmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1};
            VkCommandBuffer tempCmdBuffer = VK_NULL_HANDLE;
            result = vkAllocateCommandBuffers(device, &cmdBufferInfo, &tempCmdBuffer);
            
            if (result == VK_SUCCESS) {
                VkCommandBufferBeginInfo beginInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, nullptr};
                result = vkBeginCommandBuffer(tempCmdBuffer, &beginInfo);
                
                if (result == VK_SUCCESS) {
                    vkCmdSetDepthBounds(tempCmdBuffer, 0.0f, 1.0f);
                    GOLOGW("vkCmdSetDepthBounds completed successfully");
                    vkEndCommandBuffer(tempCmdBuffer);
                }
            }
            vkDestroyCommandPool(device, tempCmdPool, nullptr);
        } else {
            GOLOGE("vkCmdSetDepthBounds failed with error: %d", result);
        }
    }
    
    // ==================== Test: vkCmdSetDepthBoundsTestEnable ====================
    {
        PFN_vkCmdSetDepthBoundsTestEnable pfnCmdSetDepthBoundsTestEnable = 
            reinterpret_cast<PFN_vkCmdSetDepthBoundsTestEnable>(vkGetDeviceProcAddr(device, "vkCmdSetDepthBoundsTestEnable"));
        
        if (pfnCmdSetDepthBoundsTestEnable == nullptr) {
            GOLOGE("vkCmdSetDepthBoundsTestEnable failed with error: function not available in driver");
        } else {
            VkCommandPoolCreateInfo cmdPoolInfo{VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, nullptr, 0, OHTestApp::Device::Instance().GetQueueFamilyIndex()};
            VkCommandPool tempCmdPool = VK_NULL_HANDLE;
            VkResult result = vkCreateCommandPool(device, &cmdPoolInfo, nullptr, &tempCmdPool);
            
            if (result == VK_SUCCESS) {
                VkCommandBufferAllocateInfo cmdBufferInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, nullptr, tempCmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1};
                VkCommandBuffer tempCmdBuffer = VK_NULL_HANDLE;
                result = vkAllocateCommandBuffers(device, &cmdBufferInfo, &tempCmdBuffer);
                
                if (result == VK_SUCCESS) {
                    VkCommandBufferBeginInfo beginInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, nullptr};
                    result = vkBeginCommandBuffer(tempCmdBuffer, &beginInfo);
                    
                    if (result == VK_SUCCESS) {
                        pfnCmdSetDepthBoundsTestEnable(tempCmdBuffer, VK_TRUE);
                        GOLOGW("vkCmdSetDepthBoundsTestEnable completed successfully");
                        vkEndCommandBuffer(tempCmdBuffer);
                    }
                }
                vkDestroyCommandPool(device, tempCmdPool, nullptr);
            } else {
                GOLOGE("vkCmdSetDepthBoundsTestEnable failed with error: %d", result);
            }
        }
    }
    
    // ==================== Test: vkCmdSetDepthCompareOp ====================
    {
        PFN_vkCmdSetDepthCompareOp pfnCmdSetDepthCompareOp = 
            reinterpret_cast<PFN_vkCmdSetDepthCompareOp>(vkGetDeviceProcAddr(device, "vkCmdSetDepthCompareOp"));
        
        if (pfnCmdSetDepthCompareOp == nullptr) {
            GOLOGE("vkCmdSetDepthCompareOp failed with error: function not available in driver");
        } else {
            VkCommandPoolCreateInfo cmdPoolInfo{VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, nullptr, 0, OHTestApp::Device::Instance().GetQueueFamilyIndex()};
            VkCommandPool tempCmdPool = VK_NULL_HANDLE;
            VkResult result = vkCreateCommandPool(device, &cmdPoolInfo, nullptr, &tempCmdPool);
            
            if (result == VK_SUCCESS) {
                VkCommandBufferAllocateInfo cmdBufferInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, nullptr, tempCmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1};
                VkCommandBuffer tempCmdBuffer = VK_NULL_HANDLE;
                result = vkAllocateCommandBuffers(device, &cmdBufferInfo, &tempCmdBuffer);
                
                if (result == VK_SUCCESS) {
                    VkCommandBufferBeginInfo beginInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, nullptr};
                    result = vkBeginCommandBuffer(tempCmdBuffer, &beginInfo);
                    
                    if (result == VK_SUCCESS) {
                        pfnCmdSetDepthCompareOp(tempCmdBuffer, VK_COMPARE_OP_LESS);
                        GOLOGW("vkCmdSetDepthCompareOp completed successfully");
                        vkEndCommandBuffer(tempCmdBuffer);
                    }
                }
                vkDestroyCommandPool(device, tempCmdPool, nullptr);
            } else {
                GOLOGE("vkCmdSetDepthCompareOp failed with error: %d", result);
            }
        }
    }
    
    // ==================== Test: vkCmdSetDepthTestEnable ====================
    {
        PFN_vkCmdSetDepthTestEnable pfnCmdSetDepthTestEnable = 
            reinterpret_cast<PFN_vkCmdSetDepthTestEnable>(vkGetDeviceProcAddr(device, "vkCmdSetDepthTestEnable"));
        
        if (pfnCmdSetDepthTestEnable == nullptr) {
            GOLOGE("vkCmdSetDepthTestEnable failed with error: function not available in driver");
        } else {
            VkCommandPoolCreateInfo cmdPoolInfo{VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, nullptr, 0, OHTestApp::Device::Instance().GetQueueFamilyIndex()};
            VkCommandPool tempCmdPool = VK_NULL_HANDLE;
            VkResult result = vkCreateCommandPool(device, &cmdPoolInfo, nullptr, &tempCmdPool);
            
            if (result == VK_SUCCESS) {
                VkCommandBufferAllocateInfo cmdBufferInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, nullptr, tempCmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1};
                VkCommandBuffer tempCmdBuffer = VK_NULL_HANDLE;
                result = vkAllocateCommandBuffers(device, &cmdBufferInfo, &tempCmdBuffer);
                
                if (result == VK_SUCCESS) {
                    VkCommandBufferBeginInfo beginInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, nullptr};
                    result = vkBeginCommandBuffer(tempCmdBuffer, &beginInfo);
                    
                    if (result == VK_SUCCESS) {
                        pfnCmdSetDepthTestEnable(tempCmdBuffer, VK_TRUE);
                        GOLOGW("vkCmdSetDepthTestEnable completed successfully");
                        vkEndCommandBuffer(tempCmdBuffer);
                    }
                }
                vkDestroyCommandPool(device, tempCmdPool, nullptr);
            } else {
                GOLOGE("vkCmdSetDepthTestEnable failed with error: %d", result);
            }
        }
    }
    
    // ==================== Test: vkCmdSetDepthWriteEnable ====================
    {
        PFN_vkCmdSetDepthWriteEnable pfnCmdSetDepthWriteEnable = 
            reinterpret_cast<PFN_vkCmdSetDepthWriteEnable>(vkGetDeviceProcAddr(device, "vkCmdSetDepthWriteEnable"));
        
        if (pfnCmdSetDepthWriteEnable == nullptr) {
            GOLOGE("vkCmdSetDepthWriteEnable failed with error: function not available in driver");
        } else {
            VkCommandPoolCreateInfo cmdPoolInfo{VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, nullptr, 0, OHTestApp::Device::Instance().GetQueueFamilyIndex()};
            VkCommandPool tempCmdPool = VK_NULL_HANDLE;
            VkResult result = vkCreateCommandPool(device, &cmdPoolInfo, nullptr, &tempCmdPool);
            
            if (result == VK_SUCCESS) {
                VkCommandBufferAllocateInfo cmdBufferInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, nullptr, tempCmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1};
                VkCommandBuffer tempCmdBuffer = VK_NULL_HANDLE;
                result = vkAllocateCommandBuffers(device, &cmdBufferInfo, &tempCmdBuffer);
                
                if (result == VK_SUCCESS) {
                    VkCommandBufferBeginInfo beginInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, nullptr};
                    result = vkBeginCommandBuffer(tempCmdBuffer, &beginInfo);
                    
                    if (result == VK_SUCCESS) {
                        pfnCmdSetDepthWriteEnable(tempCmdBuffer, VK_TRUE);
                        GOLOGW("vkCmdSetDepthWriteEnable completed successfully");
                        vkEndCommandBuffer(tempCmdBuffer);
                    }
                }
                vkDestroyCommandPool(device, tempCmdPool, nullptr);
            } else {
                GOLOGE("vkCmdSetDepthWriteEnable failed with error: %d", result);
            }
        }
    }
    
    // ==================== Test: vkCmdSetDeviceMask ====================
    {
        VkCommandPoolCreateInfo cmdPoolInfo{VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, nullptr, 0, OHTestApp::Device::Instance().GetQueueFamilyIndex()};
        VkCommandPool tempCmdPool = VK_NULL_HANDLE;
        VkResult result = vkCreateCommandPool(device, &cmdPoolInfo, nullptr, &tempCmdPool);
        
        if (result == VK_SUCCESS) {
            VkCommandBufferAllocateInfo cmdBufferInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, nullptr, tempCmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1};
            VkCommandBuffer tempCmdBuffer = VK_NULL_HANDLE;
            result = vkAllocateCommandBuffers(device, &cmdBufferInfo, &tempCmdBuffer);
            
            if (result == VK_SUCCESS) {
                VkCommandBufferBeginInfo beginInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, nullptr};
                result = vkBeginCommandBuffer(tempCmdBuffer, &beginInfo);
                
                if (result == VK_SUCCESS) {
                    vkCmdSetDeviceMask(tempCmdBuffer, 1);
                    GOLOGW("vkCmdSetDeviceMask completed successfully");
                    vkEndCommandBuffer(tempCmdBuffer);
                }
            }
            vkDestroyCommandPool(device, tempCmdPool, nullptr);
        } else {
            GOLOGE("vkCmdSetDeviceMask failed with error: %d", result);
        }
    }
    
    // ==================== Test: vkCmdSetEvent ====================
    {
        VkEventCreateInfo eventInfo{VK_STRUCTURE_TYPE_EVENT_CREATE_INFO, nullptr, 0};
        VkEvent event = VK_NULL_HANDLE;
        VkResult result = vkCreateEvent(device, &eventInfo, nullptr, &event);
        
        if (result == VK_SUCCESS) {
            VkCommandPoolCreateInfo cmdPoolInfo{VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, nullptr, 0, OHTestApp::Device::Instance().GetQueueFamilyIndex()};
            VkCommandPool tempCmdPool = VK_NULL_HANDLE;
            result = vkCreateCommandPool(device, &cmdPoolInfo, nullptr, &tempCmdPool);
            
            if (result == VK_SUCCESS) {
                VkCommandBufferAllocateInfo cmdBufferInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, nullptr, tempCmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1};
                VkCommandBuffer tempCmdBuffer = VK_NULL_HANDLE;
                result = vkAllocateCommandBuffers(device, &cmdBufferInfo, &tempCmdBuffer);
                
                if (result == VK_SUCCESS) {
                    VkCommandBufferBeginInfo beginInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, nullptr};
                    result = vkBeginCommandBuffer(tempCmdBuffer, &beginInfo);
                    
                    if (result == VK_SUCCESS) {
                        vkCmdSetEvent(tempCmdBuffer, event, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
                        GOLOGW("vkCmdSetEvent completed successfully");
                        vkEndCommandBuffer(tempCmdBuffer);
                    }
                }
                vkDestroyCommandPool(device, tempCmdPool, nullptr);
            }
            vkDestroyEvent(device, event, nullptr);
        } else {
            GOLOGE("vkCmdSetEvent failed with error: %d", result);
        }
    }
    
    // ==================== Test: vkCmdSetFrontFace ====================
    {
        PFN_vkCmdSetFrontFace pfnCmdSetFrontFace = 
            reinterpret_cast<PFN_vkCmdSetFrontFace>(vkGetDeviceProcAddr(device, "vkCmdSetFrontFace"));
        
        if (pfnCmdSetFrontFace == nullptr) {
            GOLOGE("vkCmdSetFrontFace failed with error: function not available in driver");
        } else {
            VkCommandPoolCreateInfo cmdPoolInfo{VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, nullptr, 0, OHTestApp::Device::Instance().GetQueueFamilyIndex()};
            VkCommandPool tempCmdPool = VK_NULL_HANDLE;
            VkResult result = vkCreateCommandPool(device, &cmdPoolInfo, nullptr, &tempCmdPool);
            
            if (result == VK_SUCCESS) {
                VkCommandBufferAllocateInfo cmdBufferInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, nullptr, tempCmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1};
                VkCommandBuffer tempCmdBuffer = VK_NULL_HANDLE;
                result = vkAllocateCommandBuffers(device, &cmdBufferInfo, &tempCmdBuffer);
                
                if (result == VK_SUCCESS) {
                    VkCommandBufferBeginInfo beginInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, nullptr};
                    result = vkBeginCommandBuffer(tempCmdBuffer, &beginInfo);
                    
                    if (result == VK_SUCCESS) {
                        pfnCmdSetFrontFace(tempCmdBuffer, VK_FRONT_FACE_COUNTER_CLOCKWISE);
                        GOLOGW("vkCmdSetFrontFace completed successfully");
                        vkEndCommandBuffer(tempCmdBuffer);
                    }
                }
                vkDestroyCommandPool(device, tempCmdPool, nullptr);
            } else {
                GOLOGE("vkCmdSetFrontFace failed with error: %d", result);
            }
        }
    }
    
    // ==================== Test: vkCmdSetLineWidth ====================
    {
        VkCommandPoolCreateInfo cmdPoolInfo{VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, nullptr, 0, OHTestApp::Device::Instance().GetQueueFamilyIndex()};
        VkCommandPool tempCmdPool = VK_NULL_HANDLE;
        VkResult result = vkCreateCommandPool(device, &cmdPoolInfo, nullptr, &tempCmdPool);
        
        if (result == VK_SUCCESS) {
            VkCommandBufferAllocateInfo cmdBufferInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, nullptr, tempCmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1};
            VkCommandBuffer tempCmdBuffer = VK_NULL_HANDLE;
            result = vkAllocateCommandBuffers(device, &cmdBufferInfo, &tempCmdBuffer);
            
            if (result == VK_SUCCESS) {
                VkCommandBufferBeginInfo beginInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, nullptr};
                result = vkBeginCommandBuffer(tempCmdBuffer, &beginInfo);
                
                if (result == VK_SUCCESS) {
                    vkCmdSetLineWidth(tempCmdBuffer, 1.0f);
                    GOLOGW("vkCmdSetLineWidth completed successfully");
                    vkEndCommandBuffer(tempCmdBuffer);
                }
            }
            vkDestroyCommandPool(device, tempCmdPool, nullptr);
        } else {
            GOLOGE("vkCmdSetLineWidth failed with error: %d", result);
        }
    }
    
    // ==================== Test: vkCmdSetPrimitiveRestartEnable ====================
    {
        PFN_vkCmdSetPrimitiveRestartEnable pfnCmdSetPrimitiveRestartEnable = 
            reinterpret_cast<PFN_vkCmdSetPrimitiveRestartEnable>(vkGetDeviceProcAddr(device, "vkCmdSetPrimitiveRestartEnable"));
        
        if (pfnCmdSetPrimitiveRestartEnable == nullptr) {
            GOLOGE("vkCmdSetPrimitiveRestartEnable failed with error: function not available in driver");
        } else {
            VkCommandPoolCreateInfo cmdPoolInfo{VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, nullptr, 0, OHTestApp::Device::Instance().GetQueueFamilyIndex()};
            VkCommandPool tempCmdPool = VK_NULL_HANDLE;
            VkResult result = vkCreateCommandPool(device, &cmdPoolInfo, nullptr, &tempCmdPool);
            
            if (result == VK_SUCCESS) {
                VkCommandBufferAllocateInfo cmdBufferInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, nullptr, tempCmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1};
                VkCommandBuffer tempCmdBuffer = VK_NULL_HANDLE;
                result = vkAllocateCommandBuffers(device, &cmdBufferInfo, &tempCmdBuffer);
                
                if (result == VK_SUCCESS) {
                    VkCommandBufferBeginInfo beginInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, nullptr};
                    result = vkBeginCommandBuffer(tempCmdBuffer, &beginInfo);
                    
                    if (result == VK_SUCCESS) {
                        pfnCmdSetPrimitiveRestartEnable(tempCmdBuffer, VK_FALSE);
                        GOLOGW("vkCmdSetPrimitiveRestartEnable completed successfully");
                        vkEndCommandBuffer(tempCmdBuffer);
                    }
                }
                vkDestroyCommandPool(device, tempCmdPool, nullptr);
            } else {
                GOLOGE("vkCmdSetPrimitiveRestartEnable failed with error: %d", result);
            }
        }
    }
    
    // ==================== Test: vkCmdSetPrimitiveTopology ====================
    {
        PFN_vkCmdSetPrimitiveTopology pfnCmdSetPrimitiveTopology = 
            reinterpret_cast<PFN_vkCmdSetPrimitiveTopology>(vkGetDeviceProcAddr(device, "vkCmdSetPrimitiveTopology"));
        
        if (pfnCmdSetPrimitiveTopology == nullptr) {
            GOLOGE("vkCmdSetPrimitiveTopology failed with error: function not available in driver");
        } else {
            VkCommandPoolCreateInfo cmdPoolInfo{VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, nullptr, 0, OHTestApp::Device::Instance().GetQueueFamilyIndex()};
            VkCommandPool tempCmdPool = VK_NULL_HANDLE;
            VkResult result = vkCreateCommandPool(device, &cmdPoolInfo, nullptr, &tempCmdPool);
            
            if (result == VK_SUCCESS) {
                VkCommandBufferAllocateInfo cmdBufferInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, nullptr, tempCmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1};
                VkCommandBuffer tempCmdBuffer = VK_NULL_HANDLE;
                result = vkAllocateCommandBuffers(device, &cmdBufferInfo, &tempCmdBuffer);
                
                if (result == VK_SUCCESS) {
                    VkCommandBufferBeginInfo beginInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, nullptr};
                    result = vkBeginCommandBuffer(tempCmdBuffer, &beginInfo);
                    
                    if (result == VK_SUCCESS) {
                        pfnCmdSetPrimitiveTopology(tempCmdBuffer, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST);
                        GOLOGW("vkCmdSetPrimitiveTopology completed successfully");
                        vkEndCommandBuffer(tempCmdBuffer);
                    }
                }
                vkDestroyCommandPool(device, tempCmdPool, nullptr);
            } else {
                GOLOGE("vkCmdSetPrimitiveTopology failed with error: %d", result);
            }
        }
    }
    
    // ==================== Test: vkCmdSetRasterizerDiscardEnable ====================
    {
        PFN_vkCmdSetRasterizerDiscardEnable pfnCmdSetRasterizerDiscardEnable = 
            reinterpret_cast<PFN_vkCmdSetRasterizerDiscardEnable>(vkGetDeviceProcAddr(device, "vkCmdSetRasterizerDiscardEnable"));
        
        if (pfnCmdSetRasterizerDiscardEnable == nullptr) {
            GOLOGE("vkCmdSetRasterizerDiscardEnable failed with error: function not available in driver");
        } else {
            VkCommandPoolCreateInfo cmdPoolInfo{VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, nullptr, 0, OHTestApp::Device::Instance().GetQueueFamilyIndex()};
            VkCommandPool tempCmdPool = VK_NULL_HANDLE;
            VkResult result = vkCreateCommandPool(device, &cmdPoolInfo, nullptr, &tempCmdPool);
            
            if (result == VK_SUCCESS) {
                VkCommandBufferAllocateInfo cmdBufferInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, nullptr, tempCmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1};
                VkCommandBuffer tempCmdBuffer = VK_NULL_HANDLE;
                result = vkAllocateCommandBuffers(device, &cmdBufferInfo, &tempCmdBuffer);
                
                if (result == VK_SUCCESS) {
                    VkCommandBufferBeginInfo beginInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, nullptr};
                    result = vkBeginCommandBuffer(tempCmdBuffer, &beginInfo);
                    
                    if (result == VK_SUCCESS) {
                        pfnCmdSetRasterizerDiscardEnable(tempCmdBuffer, VK_FALSE);
                        GOLOGW("vkCmdSetRasterizerDiscardEnable completed successfully");
                        vkEndCommandBuffer(tempCmdBuffer);
                    }
                }
                vkDestroyCommandPool(device, tempCmdPool, nullptr);
            } else {
                GOLOGE("vkCmdSetRasterizerDiscardEnable failed with error: %d", result);
            }
        }
    }
    
    // ==================== Test: vkCmdSetScissorWithCount ====================
    {
        PFN_vkCmdSetScissorWithCount pfnCmdSetScissorWithCount = 
            reinterpret_cast<PFN_vkCmdSetScissorWithCount>(vkGetDeviceProcAddr(device, "vkCmdSetScissorWithCount"));
        
        if (pfnCmdSetScissorWithCount == nullptr) {
            GOLOGE("vkCmdSetScissorWithCount failed with error: function not available in driver");
        } else {
            VkCommandPoolCreateInfo cmdPoolInfo{VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, nullptr, 0, OHTestApp::Device::Instance().GetQueueFamilyIndex()};
            VkCommandPool tempCmdPool = VK_NULL_HANDLE;
            VkResult result = vkCreateCommandPool(device, &cmdPoolInfo, nullptr, &tempCmdPool);
            
            if (result == VK_SUCCESS) {
                VkCommandBufferAllocateInfo cmdBufferInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, nullptr, tempCmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1};
                VkCommandBuffer tempCmdBuffer = VK_NULL_HANDLE;
                result = vkAllocateCommandBuffers(device, &cmdBufferInfo, &tempCmdBuffer);
                
                if (result == VK_SUCCESS) {
                    VkCommandBufferBeginInfo beginInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, nullptr};
                    result = vkBeginCommandBuffer(tempCmdBuffer, &beginInfo);
                    
                    if (result == VK_SUCCESS) {
                        VkRect2D scissor{{0, 0}, {256, 256}};
                        pfnCmdSetScissorWithCount(tempCmdBuffer, 1, &scissor);
                        GOLOGW("vkCmdSetScissorWithCount completed successfully");
                        vkEndCommandBuffer(tempCmdBuffer);
                    }
                }
                vkDestroyCommandPool(device, tempCmdPool, nullptr);
            } else {
                GOLOGE("vkCmdSetScissorWithCount failed with error: %d", result);
            }
        }
    }
    
    // ==================== Test: vkCmdSetStencilCompareMask ====================
    {
        VkCommandPoolCreateInfo cmdPoolInfo{VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, nullptr, 0, OHTestApp::Device::Instance().GetQueueFamilyIndex()};
        VkCommandPool tempCmdPool = VK_NULL_HANDLE;
        VkResult result = vkCreateCommandPool(device, &cmdPoolInfo, nullptr, &tempCmdPool);
        
        if (result == VK_SUCCESS) {
            VkCommandBufferAllocateInfo cmdBufferInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, nullptr, tempCmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1};
            VkCommandBuffer tempCmdBuffer = VK_NULL_HANDLE;
            result = vkAllocateCommandBuffers(device, &cmdBufferInfo, &tempCmdBuffer);
            
            if (result == VK_SUCCESS) {
                VkCommandBufferBeginInfo beginInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, nullptr};
                result = vkBeginCommandBuffer(tempCmdBuffer, &beginInfo);
                
                if (result == VK_SUCCESS) {
                    vkCmdSetStencilCompareMask(tempCmdBuffer, VK_STENCIL_FACE_FRONT_AND_BACK, 0xFF);
                    GOLOGW("vkCmdSetStencilCompareMask completed successfully");
                    vkEndCommandBuffer(tempCmdBuffer);
                }
            }
            vkDestroyCommandPool(device, tempCmdPool, nullptr);
        } else {
            GOLOGE("vkCmdSetStencilCompareMask failed with error: %d", result);
        }
    }
    
    // ==================== Test: vkCmdSetStencilOp ====================
    {
        PFN_vkCmdSetStencilOp pfnCmdSetStencilOp = 
            reinterpret_cast<PFN_vkCmdSetStencilOp>(vkGetDeviceProcAddr(device, "vkCmdSetStencilOp"));
        
        if (pfnCmdSetStencilOp == nullptr) {
            GOLOGE("vkCmdSetStencilOp failed with error: function not available in driver");
        } else {
            VkCommandPoolCreateInfo cmdPoolInfo{VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, nullptr, 0, OHTestApp::Device::Instance().GetQueueFamilyIndex()};
            VkCommandPool tempCmdPool = VK_NULL_HANDLE;
            VkResult result = vkCreateCommandPool(device, &cmdPoolInfo, nullptr, &tempCmdPool);
            
            if (result == VK_SUCCESS) {
                VkCommandBufferAllocateInfo cmdBufferInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, nullptr, tempCmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1};
                VkCommandBuffer tempCmdBuffer = VK_NULL_HANDLE;
                result = vkAllocateCommandBuffers(device, &cmdBufferInfo, &tempCmdBuffer);
                
                if (result == VK_SUCCESS) {
                    VkCommandBufferBeginInfo beginInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, nullptr};
                    result = vkBeginCommandBuffer(tempCmdBuffer, &beginInfo);
                    
                    if (result == VK_SUCCESS) {
                        pfnCmdSetStencilOp(tempCmdBuffer, VK_STENCIL_FACE_FRONT_AND_BACK, 
                                          VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP, VK_COMPARE_OP_ALWAYS);
                        GOLOGW("vkCmdSetStencilOp completed successfully");
                        vkEndCommandBuffer(tempCmdBuffer);
                    }
                }
                vkDestroyCommandPool(device, tempCmdPool, nullptr);
            } else {
                GOLOGE("vkCmdSetStencilOp failed with error: %d", result);
            }
        }
    }
    
    // ==================== Test: vkCmdSetStencilTestEnable ====================
    {
        PFN_vkCmdSetStencilTestEnable pfnCmdSetStencilTestEnable = 
            reinterpret_cast<PFN_vkCmdSetStencilTestEnable>(vkGetDeviceProcAddr(device, "vkCmdSetStencilTestEnable"));
        
        if (pfnCmdSetStencilTestEnable == nullptr) {
            GOLOGE("vkCmdSetStencilTestEnable failed with error: function not available in driver");
        } else {
            VkCommandPoolCreateInfo cmdPoolInfo{VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, nullptr, 0, OHTestApp::Device::Instance().GetQueueFamilyIndex()};
            VkCommandPool tempCmdPool = VK_NULL_HANDLE;
            VkResult result = vkCreateCommandPool(device, &cmdPoolInfo, nullptr, &tempCmdPool);
            
            if (result == VK_SUCCESS) {
                VkCommandBufferAllocateInfo cmdBufferInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, nullptr, tempCmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1};
                VkCommandBuffer tempCmdBuffer = VK_NULL_HANDLE;
                result = vkAllocateCommandBuffers(device, &cmdBufferInfo, &tempCmdBuffer);
                
                if (result == VK_SUCCESS) {
                    VkCommandBufferBeginInfo beginInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, nullptr};
                    result = vkBeginCommandBuffer(tempCmdBuffer, &beginInfo);
                    
                    if (result == VK_SUCCESS) {
                        pfnCmdSetStencilTestEnable(tempCmdBuffer, VK_FALSE);
                        GOLOGW("vkCmdSetStencilTestEnable completed successfully");
                        vkEndCommandBuffer(tempCmdBuffer);
                    }
                }
                vkDestroyCommandPool(device, tempCmdPool, nullptr);
            } else {
                GOLOGE("vkCmdSetStencilTestEnable failed with error: %d", result);
            }
        }
    }
    
    // ==================== Test: vkCmdSetStencilWriteMask ====================
    {
        VkCommandPoolCreateInfo cmdPoolInfo{VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, nullptr, 0, OHTestApp::Device::Instance().GetQueueFamilyIndex()};
        VkCommandPool tempCmdPool = VK_NULL_HANDLE;
        VkResult result = vkCreateCommandPool(device, &cmdPoolInfo, nullptr, &tempCmdPool);
        
        if (result == VK_SUCCESS) {
            VkCommandBufferAllocateInfo cmdBufferInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, nullptr, tempCmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1};
            VkCommandBuffer tempCmdBuffer = VK_NULL_HANDLE;
            result = vkAllocateCommandBuffers(device, &cmdBufferInfo, &tempCmdBuffer);
            
            if (result == VK_SUCCESS) {
                VkCommandBufferBeginInfo beginInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, nullptr};
                result = vkBeginCommandBuffer(tempCmdBuffer, &beginInfo);
                
                if (result == VK_SUCCESS) {
                    vkCmdSetStencilWriteMask(tempCmdBuffer, VK_STENCIL_FACE_FRONT_AND_BACK, 0xFF);
                    GOLOGW("vkCmdSetStencilWriteMask completed successfully");
                    vkEndCommandBuffer(tempCmdBuffer);
                }
            }
            vkDestroyCommandPool(device, tempCmdPool, nullptr);
        } else {
            GOLOGE("vkCmdSetStencilWriteMask failed with error: %d", result);
        }
    }
    
    // ==================== Test: vkCmdSetViewportWithCount ====================
    {
        PFN_vkCmdSetViewportWithCount pfnCmdSetViewportWithCount = 
            reinterpret_cast<PFN_vkCmdSetViewportWithCount>(vkGetDeviceProcAddr(device, "vkCmdSetViewportWithCount"));
        
        if (pfnCmdSetViewportWithCount == nullptr) {
            GOLOGE("vkCmdSetViewportWithCount failed with error: function not available in driver");
        } else {
            VkCommandPoolCreateInfo cmdPoolInfo{VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, nullptr, 0, OHTestApp::Device::Instance().GetQueueFamilyIndex()};
            VkCommandPool tempCmdPool = VK_NULL_HANDLE;
            VkResult result = vkCreateCommandPool(device, &cmdPoolInfo, nullptr, &tempCmdPool);
            
            if (result == VK_SUCCESS) {
                VkCommandBufferAllocateInfo cmdBufferInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, nullptr, tempCmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1};
                VkCommandBuffer tempCmdBuffer = VK_NULL_HANDLE;
                result = vkAllocateCommandBuffers(device, &cmdBufferInfo, &tempCmdBuffer);
                
                if (result == VK_SUCCESS) {
                    VkCommandBufferBeginInfo beginInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, nullptr};
                    result = vkBeginCommandBuffer(tempCmdBuffer, &beginInfo);
                    
                    if (result == VK_SUCCESS) {
                        VkViewport viewport{0.0f, 0.0f, 256.0f, 256.0f, 0.0f, 1.0f};
                        pfnCmdSetViewportWithCount(tempCmdBuffer, 1, &viewport);
                        GOLOGW("vkCmdSetViewportWithCount completed successfully");
                        vkEndCommandBuffer(tempCmdBuffer);
                    }
                }
                vkDestroyCommandPool(device, tempCmdPool, nullptr);
            } else {
                GOLOGE("vkCmdSetViewportWithCount failed with error: %d", result);
            }
        }
    }
    
    // ==================== Test: vkCmdUpdateBuffer ====================
    {
        VkBufferCreateInfo bufferInfo{VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, nullptr, 0, 256, VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_SHARING_MODE_EXCLUSIVE, 0, nullptr};
        VkBuffer buffer = VK_NULL_HANDLE;
        VkResult result = vkCreateBuffer(device, &bufferInfo, nullptr, &buffer);
        
        if (result == VK_SUCCESS) {
            VkCommandPoolCreateInfo cmdPoolInfo{VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, nullptr, 0, OHTestApp::Device::Instance().GetQueueFamilyIndex()};
            VkCommandPool tempCmdPool = VK_NULL_HANDLE;
            result = vkCreateCommandPool(device, &cmdPoolInfo, nullptr, &tempCmdPool);
            
            if (result == VK_SUCCESS) {
                VkCommandBufferAllocateInfo cmdBufferInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, nullptr, tempCmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1};
                VkCommandBuffer tempCmdBuffer = VK_NULL_HANDLE;
                result = vkAllocateCommandBuffers(device, &cmdBufferInfo, &tempCmdBuffer);
                
                if (result == VK_SUCCESS) {
                    VkCommandBufferBeginInfo beginInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, nullptr};
                    result = vkBeginCommandBuffer(tempCmdBuffer, &beginInfo);
                    
                    if (result == VK_SUCCESS) {
                        uint32_t data[4] = {1, 2, 3, 4};
                        vkCmdUpdateBuffer(tempCmdBuffer, buffer, 0, sizeof(data), data);
                        GOLOGW("vkCmdUpdateBuffer completed successfully");
                        vkEndCommandBuffer(tempCmdBuffer);
                    }
                }
                vkDestroyCommandPool(device, tempCmdPool, nullptr);
            }
            vkDestroyBuffer(device, buffer, nullptr);
        } else {
            GOLOGE("vkCmdUpdateBuffer failed with error: %d", result);
        }
    }
    
    // ==================== Test: vkCmdWaitEvents ====================
    {
        VkEventCreateInfo eventInfo{VK_STRUCTURE_TYPE_EVENT_CREATE_INFO, nullptr, 0};
        VkEvent event = VK_NULL_HANDLE;
        VkResult result = vkCreateEvent(device, &eventInfo, nullptr, &event);
        
        if (result == VK_SUCCESS) {
            VkCommandPoolCreateInfo cmdPoolInfo{VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, nullptr, 0, OHTestApp::Device::Instance().GetQueueFamilyIndex()};
            VkCommandPool tempCmdPool = VK_NULL_HANDLE;
            result = vkCreateCommandPool(device, &cmdPoolInfo, nullptr, &tempCmdPool);
            
            if (result == VK_SUCCESS) {
                VkCommandBufferAllocateInfo cmdBufferInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, nullptr, tempCmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1};
                VkCommandBuffer tempCmdBuffer = VK_NULL_HANDLE;
                result = vkAllocateCommandBuffers(device, &cmdBufferInfo, &tempCmdBuffer);
                
                if (result == VK_SUCCESS) {
                    VkCommandBufferBeginInfo beginInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, nullptr};
                    result = vkBeginCommandBuffer(tempCmdBuffer, &beginInfo);
                    
                    if (result == VK_SUCCESS) {
                        vkCmdWaitEvents(tempCmdBuffer, 1, &event, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 
                                       VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, nullptr, 0, nullptr, 0, nullptr);
                        GOLOGW("vkCmdWaitEvents completed successfully");
                        vkEndCommandBuffer(tempCmdBuffer);
                    }
                }
                vkDestroyCommandPool(device, tempCmdPool, nullptr);
            }
            vkDestroyEvent(device, event, nullptr);
        } else {
            GOLOGE("vkCmdWaitEvents failed with error: %d", result);
        }
    }
    
    // ==================== Test: vkCmdWriteTimestamp ====================
    {
        VkQueryPoolCreateInfo queryPoolInfo{VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, nullptr, 0, VK_QUERY_TYPE_TIMESTAMP, 2, 0};
        VkQueryPool queryPool = VK_NULL_HANDLE;
        VkResult result = vkCreateQueryPool(device, &queryPoolInfo, nullptr, &queryPool);
        
        if (result == VK_SUCCESS) {
            VkCommandPoolCreateInfo cmdPoolInfo{VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, nullptr, 0, OHTestApp::Device::Instance().GetQueueFamilyIndex()};
            VkCommandPool tempCmdPool = VK_NULL_HANDLE;
            result = vkCreateCommandPool(device, &cmdPoolInfo, nullptr, &tempCmdPool);
            
            if (result == VK_SUCCESS) {
                VkCommandBufferAllocateInfo cmdBufferInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, nullptr, tempCmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1};
                VkCommandBuffer tempCmdBuffer = VK_NULL_HANDLE;
                result = vkAllocateCommandBuffers(device, &cmdBufferInfo, &tempCmdBuffer);
                
                if (result == VK_SUCCESS) {
                    VkCommandBufferBeginInfo beginInfo{VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, nullptr};
                    result = vkBeginCommandBuffer(tempCmdBuffer, &beginInfo);
                    
                    if (result == VK_SUCCESS) {
                        vkCmdWriteTimestamp(tempCmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, queryPool, 0);
                        GOLOGW("vkCmdWriteTimestamp completed successfully");
                        vkEndCommandBuffer(tempCmdBuffer);
                    }
                }
                vkDestroyCommandPool(device, tempCmdPool, nullptr);
            }
            vkDestroyQueryPool(device, queryPool, nullptr);
        } else {
            GOLOGE("vkCmdWriteTimestamp failed with error: %d", result);
        }
    }
    
    // ==================== Test: vkCreateBufferView & vkDestroyBufferView ====================
    {
        VkBufferCreateInfo bufferInfo{VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, nullptr, 0, 1024, VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, VK_SHARING_MODE_EXCLUSIVE, 0, nullptr};
        VkBuffer buffer = VK_NULL_HANDLE;
        VkResult result = vkCreateBuffer(device, &bufferInfo, nullptr, &buffer);
        
        if (result == VK_SUCCESS) {
            VkBufferViewCreateInfo viewInfo{VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO, nullptr, 0, buffer, VK_FORMAT_R8G8B8A8_UNORM, 0, 256};
            VkBufferView bufferView = VK_NULL_HANDLE;
            result = vkCreateBufferView(device, &viewInfo, nullptr, &bufferView);
            
            if (result == VK_SUCCESS) {
                GOLOGW("vkCreateBufferView completed successfully");
                vkDestroyBufferView(device, bufferView, nullptr);
                GOLOGW("vkDestroyBufferView completed successfully");
            } else {
                GOLOGE("vkCreateBufferView failed with error: %d", result);
            }
            vkDestroyBuffer(device, buffer, nullptr);
        } else {
            GOLOGE("vkCreateBufferView failed with error: %d (buffer creation)", result);
        }
    }
    
    // ==================== Test: vkCreateDescriptorUpdateTemplate & vkDestroyDescriptorUpdateTemplate ====================
    {
        VkDescriptorUpdateTemplateEntry entry{0, 0, 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, sizeof(VkDescriptorBufferInfo)};
        VkDescriptorUpdateTemplateCreateInfo templateInfo{
            VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO, nullptr, 0,
            1, &entry, VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET,
            VK_NULL_HANDLE, VK_PIPELINE_BIND_POINT_GRAPHICS, VK_NULL_HANDLE, 0
        };
        
        VkDescriptorUpdateTemplate updateTemplate = VK_NULL_HANDLE;
        VkResult result = vkCreateDescriptorUpdateTemplate(device, &templateInfo, nullptr, &updateTemplate);
        
        if (result == VK_SUCCESS) {
            GOLOGW("vkCreateDescriptorUpdateTemplate completed successfully");
            vkDestroyDescriptorUpdateTemplate(device, updateTemplate, nullptr);
            GOLOGW("vkDestroyDescriptorUpdateTemplate completed successfully");
        } else {
            GOLOGE("vkCreateDescriptorUpdateTemplate failed with error: %d", result);
        }
    }
     
    // ==================== Test: vkCreateEvent & vkDestroyEvent ====================
    {
        VkEventCreateInfo eventInfo{VK_STRUCTURE_TYPE_EVENT_CREATE_INFO, nullptr, 0};
        VkEvent event = VK_NULL_HANDLE;
        VkResult result = vkCreateEvent(device, &eventInfo, nullptr, &event);
        
        if (result == VK_SUCCESS) {
            GOLOGW("vkCreateEvent completed successfully");
            vkDestroyEvent(device, event, nullptr);
            GOLOGW("vkDestroyEvent completed successfully");
        } else {
            GOLOGE("vkCreateEvent failed with error: %d", result);
        }
    }
    
    // ==================== Test: vkCreatePipelineCache & vkDestroyPipelineCache ====================
    {
        VkPipelineCacheCreateInfo cacheInfo{VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO, nullptr, 0, 0, nullptr};
        VkPipelineCache pipelineCache = VK_NULL_HANDLE;
        VkResult result = vkCreatePipelineCache(device, &cacheInfo, nullptr, &pipelineCache);
        
        if (result == VK_SUCCESS) {
            GOLOGW("vkCreatePipelineCache completed successfully");
            vkDestroyPipelineCache(device, pipelineCache, nullptr);
            GOLOGW("vkDestroyPipelineCache completed successfully");
        } else {
            GOLOGE("vkCreatePipelineCache failed with error: %d", result);
        }
    }
    
    // ==================== Test: vkCreatePrivateDataSlot & vkDestroyPrivateDataSlot ====================
    {
        PFN_vkCreatePrivateDataSlot pfnCreatePrivateDataSlot = 
            reinterpret_cast<PFN_vkCreatePrivateDataSlot>(vkGetDeviceProcAddr(device, "vkCreatePrivateDataSlot"));
        
        if (pfnCreatePrivateDataSlot == nullptr) {
            GOLOGE("vkCreatePrivateDataSlot failed with error: function not available in driver");
        } else {
            VkPrivateDataSlotCreateInfo slotInfo{VK_STRUCTURE_TYPE_PRIVATE_DATA_SLOT_CREATE_INFO, nullptr, 0};
            VkPrivateDataSlot privateDataSlot = VK_NULL_HANDLE;
            VkResult result = pfnCreatePrivateDataSlot(device, &slotInfo, nullptr, &privateDataSlot);
            
            if (result == VK_SUCCESS) {
                GOLOGW("vkCreatePrivateDataSlot completed successfully");
                PFN_vkDestroyPrivateDataSlot pfnDestroyPrivateDataSlot = 
                    reinterpret_cast<PFN_vkDestroyPrivateDataSlot>(vkGetDeviceProcAddr(device, "vkDestroyPrivateDataSlot"));
                if (pfnDestroyPrivateDataSlot) {
                    pfnDestroyPrivateDataSlot(device, privateDataSlot, nullptr);
                    GOLOGW("vkDestroyPrivateDataSlot completed successfully");
                }
            } else {
                GOLOGE("vkCreatePrivateDataSlot failed with error: %d", result);
            }
        }
    }
    
    // ==================== Test: vkCreateQueryPool & vkDestroyQueryPool ====================
    {
        VkQueryPoolCreateInfo queryPoolInfo{VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, nullptr, 0, VK_QUERY_TYPE_OCCLUSION, 4, 0};
        VkQueryPool queryPool = VK_NULL_HANDLE;
        VkResult result = vkCreateQueryPool(device, &queryPoolInfo, nullptr, &queryPool);
        
        if (result == VK_SUCCESS) {
            GOLOGW("vkCreateQueryPool completed successfully");
            vkDestroyQueryPool(device, queryPool, nullptr);
            GOLOGW("vkDestroyQueryPool completed successfully");
        } else {
            GOLOGE("vkCreateQueryPool failed with error: %d", result);
        }
    }

    // ==================== Test: vkCreateSamplerYcbcrConversion & vkDestroySamplerYcbcrConversion ====================
    {
        // 首先检查API是否可用
        PFN_vkCreateSamplerYcbcrConversion pfnCreateYcbcrConversion = 
            reinterpret_cast<PFN_vkCreateSamplerYcbcrConversion>(
                vkGetDeviceProcAddr(device, "vkCreateSamplerYcbcrConversion"));
        
        if (pfnCreateYcbcrConversion == nullptr) {
            // 尝试KHR版本
            pfnCreateYcbcrConversion = reinterpret_cast<PFN_vkCreateSamplerYcbcrConversion>(
                vkGetDeviceProcAddr(device, "vkCreateSamplerYcbcrConversionKHR"));
        }
        
        if (pfnCreateYcbcrConversion == nullptr) {
            GOLOGE("vkCreateSamplerYcbcrConversion failed with error: function not available in driver");
        } else {
            // 创建YCbCr转换对象 (使用常见的NV12格式)
            VkSamplerYcbcrConversionCreateInfo ycbcrInfo{};
            ycbcrInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO;
            ycbcrInfo.pNext = nullptr;
            ycbcrInfo.format = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM;  // NV12格式
            ycbcrInfo.ycbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709;
            ycbcrInfo.ycbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_FULL;
            ycbcrInfo.components = {
                VK_COMPONENT_SWIZZLE_IDENTITY,
                VK_COMPONENT_SWIZZLE_IDENTITY,
                VK_COMPONENT_SWIZZLE_IDENTITY,
                VK_COMPONENT_SWIZZLE_IDENTITY
            };
            ycbcrInfo.xChromaOffset = VK_CHROMA_LOCATION_MIDPOINT;
            ycbcrInfo.yChromaOffset = VK_CHROMA_LOCATION_MIDPOINT;
            ycbcrInfo.chromaFilter = VK_FILTER_LINEAR;
            ycbcrInfo.forceExplicitReconstruction = VK_FALSE;
            
            VkSamplerYcbcrConversion ycbcrConversion = VK_NULL_HANDLE;
            VkResult result = pfnCreateYcbcrConversion(device, &ycbcrInfo, nullptr, &ycbcrConversion);
            
            if (result == VK_SUCCESS) {
                GOLOGW("vkCreateSamplerYcbcrConversion completed successfully");
                
                // 销毁YCbCr转换对象
                PFN_vkDestroySamplerYcbcrConversion pfnDestroyYcbcrConversion = 
                    reinterpret_cast<PFN_vkDestroySamplerYcbcrConversion>(
                        vkGetDeviceProcAddr(device, "vkDestroySamplerYcbcrConversion"));
                
                if (pfnDestroyYcbcrConversion == nullptr) {
                    pfnDestroyYcbcrConversion = reinterpret_cast<PFN_vkDestroySamplerYcbcrConversion>(
                        vkGetDeviceProcAddr(device, "vkDestroySamplerYcbcrConversionKHR"));
                }
                
                if (pfnDestroyYcbcrConversion) {
                    pfnDestroyYcbcrConversion(device, ycbcrConversion, nullptr);
                    GOLOGW("vkDestroySamplerYcbcrConversion completed successfully");
                }
            } else {
                GOLOGE("vkCreateSamplerYcbcrConversion failed with error: %d", result);
            }
        }
    }
    
    // ==================== Test: vkEnumerateDeviceLayerProperties ====================
    {
        uint32_t layerCount = 0;
        VkResult result = vkEnumerateDeviceLayerProperties(m_physicalDevice, &layerCount, nullptr);
        
        if (result == VK_SUCCESS) {
            GOLOGW("vkEnumerateDeviceLayerProperties (count) completed successfully, found %u layers", layerCount);
            
            if (layerCount > 0) {
                std::vector<VkLayerProperties> layers(layerCount);
                result = vkEnumerateDeviceLayerProperties(m_physicalDevice, &layerCount, layers.data());
                
                if (result == VK_SUCCESS) {
                    GOLOGW("vkEnumerateDeviceLayerProperties (data) completed successfully");
                } else {
                    GOLOGE("vkEnumerateDeviceLayerProperties (data) failed with error: %d", result);
                }
            }
        } else {
            GOLOGE("vkEnumerateDeviceLayerProperties (count) failed with error: %d", result);
        }
    }
    
    // ==================== Test: vkEnumerateInstanceVersion ====================
    {
        uint32_t apiVersion = 0;
        VkResult result = vkEnumerateInstanceVersion(&apiVersion);
        
        if (result == VK_SUCCESS) {
            uint32_t major = VK_VERSION_MAJOR(apiVersion);
            uint32_t minor = VK_VERSION_MINOR(apiVersion);
            uint32_t patch = VK_VERSION_PATCH(apiVersion);
            GOLOGW("vkEnumerateInstanceVersion completed successfully: Vulkan %u.%u.%u", major, minor, patch);
        } else {
            GOLOGE("vkEnumerateInstanceVersion failed with error: %d", result);
        }
    }
    
    // ==================== Test: vkEnumeratePhysicalDeviceGroups ====================
    {
        uint32_t deviceGroupCount = 0;
        VkResult result = vkEnumeratePhysicalDeviceGroups(m_instance, &deviceGroupCount, nullptr);
        
        if (result == VK_SUCCESS) {
            GOLOGW("vkEnumeratePhysicalDeviceGroups (count) completed successfully, found %u device groups", deviceGroupCount);
            
            if (deviceGroupCount > 0) {
                std::vector<VkPhysicalDeviceGroupProperties> deviceGroups(deviceGroupCount);
                for (auto& group : deviceGroups) {
                    group.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES;
                    group.pNext = nullptr;
                }
                
                result = vkEnumeratePhysicalDeviceGroups(m_instance, &deviceGroupCount, deviceGroups.data());
                
                if (result == VK_SUCCESS) {
                    GOLOGW("vkEnumeratePhysicalDeviceGroups (data) completed successfully");
                } else {
                    GOLOGE("vkEnumeratePhysicalDeviceGroups (data) failed with error: %d", result);
                }
            }
        } else {
            GOLOGE("vkEnumeratePhysicalDeviceGroups (count) failed with error: %d", result);
        }
    }
    
    // ==================== Test: vkCreateSharedSwapchainsKHR ====================
    {
        // 检查API是否可用
        PFN_vkCreateSharedSwapchainsKHR pfnCreateSharedSwapchains = 
            reinterpret_cast<PFN_vkCreateSharedSwapchainsKHR>(
                vkGetDeviceProcAddr(device, "vkCreateSharedSwapchainsKHR"));
        
        if (pfnCreateSharedSwapchains == nullptr) {
            GOLOGE("vkCreateSharedSwapchainsKHR failed with error: function not available in driver (requires VK_KHR_display_swapchain extension)");
        } else {
            // 注意: vkCreateSharedSwapchainsKHR需要特殊的surface和display支持
            // 在移动设备上通常不支持此功能，这里仅测试API是否可调用
            // 我们使用当前的swapchain配置作为模板
            VkSwapchainCreateInfoKHR swapchainInfo{};
            swapchainInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
            swapchainInfo.pNext = nullptr;
            swapchainInfo.flags = 0;
            swapchainInfo.surface = m_surface;
            swapchainInfo.minImageCount = 2;
            swapchainInfo.imageFormat = m_swapChainImageFormat;
            swapchainInfo.imageColorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
            swapchainInfo.imageExtent = m_swapChainExtent;
            swapchainInfo.imageArrayLayers = 1;
            swapchainInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
            swapchainInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
            swapchainInfo.queueFamilyIndexCount = 0;
            swapchainInfo.pQueueFamilyIndices = nullptr;
            swapchainInfo.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
            swapchainInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
            swapchainInfo.presentMode = VK_PRESENT_MODE_FIFO_KHR;
            swapchainInfo.clipped = VK_TRUE;
            swapchainInfo.oldSwapchain = VK_NULL_HANDLE;
            
            VkSwapchainKHR sharedSwapchain = VK_NULL_HANDLE;
            VkResult result = pfnCreateSharedSwapchains(device, 1, &swapchainInfo, nullptr, &sharedSwapchain);
            
            if (result == VK_SUCCESS) {
                GOLOGW("vkCreateSharedSwapchainsKHR completed successfully");
                // 销毁创建的共享swapchain
                vkDestroySwapchainKHR(device, sharedSwapchain, nullptr);
                GOLOGW("vkDestroySwapchainKHR (shared) completed successfully");
            } else if (result == VK_ERROR_FEATURE_NOT_PRESENT || result == VK_ERROR_EXTENSION_NOT_PRESENT) {
                GOLOGW("vkCreateSharedSwapchainsKHR not supported on this device (expected on most mobile devices)");
            } else {
                GOLOGE("vkCreateSharedSwapchainsKHR failed with error: %d", result);
            }
        }
    }
    
    // ==================== Test: vkCreateDescriptorPool & vkDestroyDescriptorPool ====================
    {
        VkDescriptorPoolSize poolSize{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 10};
        VkDescriptorPoolCreateInfo poolInfo{VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, nullptr, 0, 10, 1, &poolSize};
        VkDescriptorPool descriptorPool = VK_NULL_HANDLE;
        VkResult result = vkCreateDescriptorPool(device, &poolInfo, nullptr, &descriptorPool);
        
        if (result == VK_SUCCESS) {
            GOLOGW("vkCreateDescriptorPool completed successfully");
            vkDestroyDescriptorPool(device, descriptorPool, nullptr);
            GOLOGW("vkDestroyDescriptorPool completed successfully");
        } else {
            GOLOGE("vkCreateDescriptorPool failed with error: %d", result);
        }
    }
    
    // ==================== Test: vkGetBufferDeviceAddress ====================
    {
        // 检查是否支持bufferDeviceAddress特性
        PFN_vkGetBufferDeviceAddress pfnGetBufferDeviceAddress = 
            reinterpret_cast<PFN_vkGetBufferDeviceAddress>(vkGetDeviceProcAddr(device, "vkGetBufferDeviceAddress"));
        
        if (pfnGetBufferDeviceAddress == nullptr) {
            // 尝试KHR版本
            pfnGetBufferDeviceAddress = reinterpret_cast<PFN_vkGetBufferDeviceAddress>(
                vkGetDeviceProcAddr(device, "vkGetBufferDeviceAddressKHR"));
        }
        
        if (pfnGetBufferDeviceAddress == nullptr) {
            GOLOGE("vkGetBufferDeviceAddress failed with error: function not available in driver");
        } else {
            // 创建支持设备地址的buffer
            VkBufferCreateInfo bufferInfo{};
            bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
            bufferInfo.size = 256;
            bufferInfo.usage = VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
            bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
            
            VkBuffer buffer = VK_NULL_HANDLE;
            VkResult result = vkCreateBuffer(device, &bufferInfo, nullptr, &buffer);
            
            if (result == VK_SUCCESS) {
                VkBufferDeviceAddressInfo addressInfo{};
                addressInfo.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO;
                addressInfo.buffer = buffer;
                
                VkDeviceAddress deviceAddress = pfnGetBufferDeviceAddress(device, &addressInfo);
                GOLOGW("vkGetBufferDeviceAddress completed successfully, address: %llu", 
                       static_cast<unsigned long long>(deviceAddress));
                
                vkDestroyBuffer(device, buffer, nullptr);
            } else {
                GOLOGE("vkGetBufferDeviceAddress failed with error: %d (buffer creation failed)", result);
            }
        }
    }
    
    // ==================== Test: vkGetBufferOpaqueCaptureAddress ====================
    {
        PFN_vkGetBufferOpaqueCaptureAddress pfnGetBufferOpaqueCaptureAddress = 
            reinterpret_cast<PFN_vkGetBufferOpaqueCaptureAddress>(
                vkGetDeviceProcAddr(device, "vkGetBufferOpaqueCaptureAddress"));
        
        if (pfnGetBufferOpaqueCaptureAddress == nullptr) {
            pfnGetBufferOpaqueCaptureAddress = reinterpret_cast<PFN_vkGetBufferOpaqueCaptureAddress>(
                vkGetDeviceProcAddr(device, "vkGetBufferOpaqueCaptureAddressKHR"));
        }
        
        if (pfnGetBufferOpaqueCaptureAddress == nullptr) {
            GOLOGE("vkGetBufferOpaqueCaptureAddress failed with error: function not available in driver");
        } else {
            VkBufferCreateInfo bufferInfo{};
            bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
            bufferInfo.size = 256;
            bufferInfo.usage = VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
            bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
            
            VkBuffer buffer = VK_NULL_HANDLE;
            VkResult result = vkCreateBuffer(device, &bufferInfo, nullptr, &buffer);
            
            if (result == VK_SUCCESS) {
                VkBufferDeviceAddressInfo addressInfo{};
                addressInfo.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO;
                addressInfo.buffer = buffer;
                
                uint64_t opaqueAddress = pfnGetBufferOpaqueCaptureAddress(device, &addressInfo);
                GOLOGW("vkGetBufferOpaqueCaptureAddress completed successfully, address: %llu", 
                       static_cast<unsigned long long>(opaqueAddress));
                
                vkDestroyBuffer(device, buffer, nullptr);
            } else {
                GOLOGE("vkGetBufferOpaqueCaptureAddress failed with error: %d (buffer creation failed)", result);
            }
        }
    }
    
    // ==================== Test: vkGetDescriptorSetLayoutSupport ====================
    {
        VkDescriptorSetLayoutBinding binding{};
        binding.binding = 0;
        binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
        binding.descriptorCount = 1;
        binding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
        binding.pImmutableSamplers = nullptr;
        
        VkDescriptorSetLayoutCreateInfo layoutInfo{};
        layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
        layoutInfo.bindingCount = 1;
        layoutInfo.pBindings = &binding;
        
        VkDescriptorSetLayoutSupport support{};
        support.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT;
        
        vkGetDescriptorSetLayoutSupport(device, &layoutInfo, &support);
        GOLOGW("vkGetDescriptorSetLayoutSupport completed successfully, supported: %s", 
               support.supported ? "true" : "false");
    }
    
    // ==================== Test: vkGetDeviceBufferMemoryRequirements ====================
    {
        PFN_vkGetDeviceBufferMemoryRequirements pfnGetDeviceBufferMemoryRequirements = 
            reinterpret_cast<PFN_vkGetDeviceBufferMemoryRequirements>(
                vkGetDeviceProcAddr(device, "vkGetDeviceBufferMemoryRequirements"));
        
        if (pfnGetDeviceBufferMemoryRequirements == nullptr) {
            pfnGetDeviceBufferMemoryRequirements = reinterpret_cast<PFN_vkGetDeviceBufferMemoryRequirements>(
                vkGetDeviceProcAddr(device, "vkGetDeviceBufferMemoryRequirementsKHR"));
        }
        
        if (pfnGetDeviceBufferMemoryRequirements == nullptr) {
            GOLOGE("vkGetDeviceBufferMemoryRequirements failed with error: function not available in driver");
        } else {
            VkBufferCreateInfo bufferInfo{};
            bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
            bufferInfo.size = 1024;
            bufferInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
            bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
            
            VkDeviceBufferMemoryRequirements deviceBufferMemoryReq{};
            deviceBufferMemoryReq.sType = VK_STRUCTURE_TYPE_DEVICE_BUFFER_MEMORY_REQUIREMENTS;
            deviceBufferMemoryReq.pCreateInfo = &bufferInfo;
            
            VkMemoryRequirements2 memoryReq{};
            memoryReq.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2;
            
            pfnGetDeviceBufferMemoryRequirements(device, &deviceBufferMemoryReq, &memoryReq);
            GOLOGW("vkGetDeviceBufferMemoryRequirements completed successfully, size: %llu", 
                   static_cast<unsigned long long>(memoryReq.memoryRequirements.size));
        }
    }
    
    // ==================== Test: vkGetDeviceGroupPeerMemoryFeatures ====================
    {
        // 这个API主要用于多GPU系统，在单GPU系统上仍然可以调用
        uint32_t heapIndex = 0;
        uint32_t localDeviceIndex = 0;
        uint32_t remoteDeviceIndex = 0;
        VkPeerMemoryFeatureFlags peerMemoryFeatures = 0;
        
        vkGetDeviceGroupPeerMemoryFeatures(device, heapIndex, localDeviceIndex, remoteDeviceIndex, &peerMemoryFeatures);
        GOLOGW("vkGetDeviceGroupPeerMemoryFeatures completed successfully, features: 0x%x", peerMemoryFeatures);
    }
}

void HelloVK::Reset(OHNativeWindow *newWindow, NativeResourceManager *newManager)
{
    m_window.reset(newWindow);
    m_assetManager = newManager;
    OHTestApp::AAssetImporter::Instance().Init(newManager);

    if (m_initialized) {
        CreateSurface();
        RecreateSwapChain();
    }
}

void HelloVK::RecreateSwapChain()
{
    VkResult result = vkDeviceWaitIdle(m_device);
    if (result == VK_SUCCESS) {
        GOLOGW("vkDeviceWaitIdle completed successfully");
    } else {
        GOLOGE("vkDeviceWaitIdle failed with error: %d", result);
    }
    CleanupSwapChain();
    CreateSwapChain();
    CreateImageViews();
    FGCreateDepthResources();
    FGCreateSwapchainSyncObjects();

    FGDestroyColorResources();
    FGCreateColorResources();
    FGDestroyUIRenderer();
    FGDestroyMainSceneRenderer();
    FGInitUIRenderer();
    FGInitMainSceneRenderer();
}

void HelloVK::Render()
{
    
    FGBalancedInterRender();
}

void HelloVK::OnOrientationChange()
{
    RecreateSwapChain();
    m_orientationChanged = false;
}

void HelloVK::CleanupSwapChain()
{
    m_sceneDepthStencil.Destroy();

    for (auto const &info : m_swapchainInfo) {
        if (info.renderEnd != VK_NULL_HANDLE) {
            GOLOGD("Destroying renderEnd semaphore");
            vkDestroySemaphore(m_device, info.renderEnd, nullptr);
            GOLOGW("vkDestroySemaphore completed successfully");
        }
    }

    m_swapchainInfo.clear();

    if (m_sceneFramebuffer != VK_NULL_HANDLE) {
        GOLOGD("Destroying framebuffer");
        vkDestroyFramebuffer(m_device, m_sceneFramebuffer, nullptr);
        GOLOGW("vkDestroyFramebuffer completed successfully");
        m_sceneFramebuffer = VK_NULL_HANDLE;
    }

    for (size_t i = 0; i < m_swapChainImageViews.size(); i++) {
        GOLOGD("Destroying image view %zu", i);
        vkDestroyImageView(m_device, m_swapChainImageViews[i], nullptr);
        GOLOGW("vkDestroyImageView completed successfully");
    }

    GOLOGD("Destroying swapchain");
    vkDestroySwapchainKHR(m_device, m_swapChain, nullptr);
    GOLOGW("vkDestroySwapchainKHR completed successfully");
}

void HelloVK::Cleanup()
{
    VkResult result = vkDeviceWaitIdle(m_device);
    if (result == VK_SUCCESS) {
        GOLOGW("vkDeviceWaitIdle completed successfully");
    } else {
        GOLOGE("vkDeviceWaitIdle failed with error: %d", result);
    }
    CleanupSwapChain();

    for (auto &info : m_framesInFlights) {
        if (info.commandPool != VK_NULL_HANDLE) {
            GOLOGD("Destroying command pool");
            vkDestroyCommandPool(m_device, info.commandPool, nullptr);
            GOLOGW("vkDestroyCommandPool completed successfully");
        }

        if (info.fence != VK_NULL_HANDLE) {
            GOLOGD("Destroying fence");
            vkDestroyFence(m_device, info.fence, nullptr);
            GOLOGW("vkDestroyFence completed successfully");
        }

        if (info.acquire != VK_NULL_HANDLE) {
            GOLOGD("Destroying acquire semaphore");
            vkDestroySemaphore(m_device, info.acquire, nullptr);
            GOLOGW("vkDestroySemaphore completed successfully");
        }
    }

    m_framesInFlights.clear();

    GOLOGD("Destroying device");
    vkDestroyDevice(m_device, nullptr);
    GOLOGW("vkDestroyDevice completed successfully");

    if (ENABLE_VALIDATION_LAYERS) {
//        DestroyDebugUtilsMessengerEXT(m_instance, m_debugMessenger, nullptr);
    }

    GOLOGD("Destroying surface");
    vkDestroySurfaceKHR(m_instance, m_surface, nullptr);
    GOLOGW("vkDestroySurfaceKHR completed successfully");
    
    GOLOGD("Destroying instance");
    vkDestroyInstance(m_instance, nullptr);
    GOLOGW("vkDestroyInstance completed successfully");
    m_initialized = false;
}

void HelloVK::SetupDebugMessenger()
{
    if (!ENABLE_VALIDATION_LAYERS) {
        return;
    }

}


std::vector<const char *> HelloVK::GetRequiredExtensions(bool enableValidationLayers)
{
    std::vector<const char *> extensions = { VK_KHR_SURFACE_EXTENSION_NAME, VK_OHOS_SURFACE_EXTENSION_NAME };

    if (enableValidationLayers) {
        extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
    }

    return extensions;
}

void HelloVK::CreateInstance()
{
    // validation layers requested, but not available!
    if (ENABLE_VALIDATION_LAYERS && !CheckValidationLayerSupport()) {
        GOLOGE("Validation layers are unavailable");
        return;
    }
    auto requiredExtensions = GetRequiredExtensions(ENABLE_VALIDATION_LAYERS);

    VkApplicationInfo appInfo{};
    appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
    appInfo.pApplicationName = "Hello Triangle";
    appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
    appInfo.pEngineName = "No Engine";
    appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
    appInfo.apiVersion = VK_API_VERSION_1_3;

    VkInstanceCreateInfo createInfo{};
    createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
    createInfo.pApplicationInfo = &appInfo;
    createInfo.enabledExtensionCount = (uint32_t)requiredExtensions.size();
    createInfo.ppEnabledExtensionNames = requiredExtensions.data();
    createInfo.pApplicationInfo = &appInfo;

    if (ENABLE_VALIDATION_LAYERS) {
//        VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo{};
//        createInfo.enabledLayerCount = static_cast<uint32_t>(m_validationLayers.size());
//        createInfo.ppEnabledLayerNames = m_validationLayers.data();
//        PopulateDebugMessengerCreateInfo(debugCreateInfo);
//        createInfo.pNext = &debugCreateInfo;
    }

    VkResult result = vkCreateInstance(&createInfo, nullptr, &m_instance);
    if (result == VK_SUCCESS) {
        GOLOGW("vkCreateInstance completed successfully");
    } else {
        GOLOGE("vkCreateInstance failed with error: %d", result);
        return;
    }

    if (ENABLE_VALIDATION_LAYERS) {
//        OHTestApp::SetupDebugLabels(m_instance);
    }

    uint32_t extensionCount = 0;
    result = vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr);
    if (result == VK_SUCCESS) {
        GOLOGW("vkEnumerateInstanceExtensionProperties (count) completed successfully");
    } else {
        GOLOGE("vkEnumerateInstanceExtensionProperties (count) failed with error: %d", result);
    }
    
    std::vector<VkExtensionProperties> extensions(extensionCount);
    result = vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions.data());
    if (result == VK_SUCCESS) {
        GOLOGW("vkEnumerateInstanceExtensionProperties (data) completed successfully");
    } else {
        GOLOGE("vkEnumerateInstanceExtensionProperties (data) failed with error: %d", result);
    }
}

/*
 * CreateSurface can only be called after the ohos ecosystem has had the
 * chance to provide a native window. This happens after the APP_CMD_START event
 * has had a chance to be called.
 *
 * Notice the window.get() call which is only valid after window has been set to
 * a non null value
 */
void HelloVK::CreateSurface()
{
    if (!m_window) {
        GOLOGE("window not initialized");
        return;
    }

    const VkSurfaceCreateInfoOHOS create_info {
        .sType = VK_STRUCTURE_TYPE_SURFACE_CREATE_INFO_OHOS,
        .pNext = nullptr,
        .flags = 0,
        .window = m_window.get()
    };

    VkResult result = vkCreateSurfaceOHOS(m_instance, &create_info, nullptr, &m_surface);
    if (result == VK_SUCCESS) {
        GOLOGW("vkCreateSurfaceOHOS completed successfully");
    } else {
        GOLOGE("vkCreateSurfaceOHOS failed with error: %d", result);
    }
}

// BEGIN DEVICE SUITABILITY
// Functions to find a suitable physical device to execute Vulkan commands.

QueueFamilyIndices HelloVK::FindQueueFamilies(VkPhysicalDevice device)
{
    QueueFamilyIndices indices;

    uint32_t queueFamilyCount = 0;
    vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr);
    GOLOGW("vkGetPhysicalDeviceQueueFamilyProperties (count) completed successfully");

    std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
    vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data());
    GOLOGW("vkGetPhysicalDeviceQueueFamilyProperties (data) completed successfully");

    int i = 0;
    for (const auto &queueFamily : queueFamilies) {
        if (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) {
            indices.graphicsFamily = i;
        }

        VkBool32 presentSupport = false;
        VkResult result = vkGetPhysicalDeviceSurfaceSupportKHR(device, i, m_surface, &presentSupport);
        if (result == VK_SUCCESS) {
            GOLOGW("vkGetPhysicalDeviceSurfaceSupportKHR completed successfully");
        } else {
            GOLOGE("vkGetPhysicalDeviceSurfaceSupportKHR failed with error: %d", result);
        }
        
        if (presentSupport) {
            indices.presentFamily = i;
        }

        if (indices.isComplete()) {
            break;
        }

        ++i;
    }
    return indices;
}

bool HelloVK::CheckDeviceExtensionSupport(VkPhysicalDevice device)
{
    uint32_t extensionCount;
    VkResult result = vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, nullptr);
    if (result == VK_SUCCESS) {
        GOLOGW("vkEnumerateDeviceExtensionProperties (count) completed successfully");
    } else {
        GOLOGE("vkEnumerateDeviceExtensionProperties (count) failed with error: %d", result);
        return false;
    }

    std::vector<VkExtensionProperties> availableExtensions(extensionCount);
    result = vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, availableExtensions.data());
    if (result == VK_SUCCESS) {
        GOLOGW("vkEnumerateDeviceExtensionProperties (data) completed successfully");
    } else {
        GOLOGE("vkEnumerateDeviceExtensionProperties (data) failed with error: %d", result);
        return false;
    }

    std::set<std::string> requiredExtensions(m_deviceExtensions.begin(), m_deviceExtensions.end());

    for (const auto &extension : availableExtensions) {
        requiredExtensions.erase(extension.extensionName);
    }

    if (ENABLE_VALIDATION_LAYERS) {
        // Workaround: Probably OHOS Vulkan bug...
//        if (requiredExtensions.size() == 1U && *requiredExtensions.cbegin() == VK_KHR_SWAPCHAIN_EXTENSION_NAME) {
//            return true;
//        }
    }

    return requiredExtensions.empty();
}

SwapChainSupportDetails HelloVK::QuerySwapChainSupport(VkPhysicalDevice device)
{
    SwapChainSupportDetails details;

    VkResult result = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, m_surface, &details.capabilities);
    if (result == VK_SUCCESS) {
        GOLOGW("vkGetPhysicalDeviceSurfaceCapabilitiesKHR completed successfully");
    } else {
        GOLOGE("vkGetPhysicalDeviceSurfaceCapabilitiesKHR failed with error: %d", result);
    }

    uint32_t formatCount;
    result = vkGetPhysicalDeviceSurfaceFormatsKHR(device, m_surface, &formatCount, nullptr);
    if (result == VK_SUCCESS) {
        GOLOGW("vkGetPhysicalDeviceSurfaceFormatsKHR (count) completed successfully");
    } else {
        GOLOGE("vkGetPhysicalDeviceSurfaceFormatsKHR (count) failed with error: %d", result);
    }

    if (formatCount != 0) {
        details.formats.resize(formatCount);
        result = vkGetPhysicalDeviceSurfaceFormatsKHR(device, m_surface, &formatCount, details.formats.data());
        if (result == VK_SUCCESS) {
            GOLOGW("vkGetPhysicalDeviceSurfaceFormatsKHR (data) completed successfully");
        } else {
            GOLOGE("vkGetPhysicalDeviceSurfaceFormatsKHR (data) failed with error: %d", result);
        }
    }

    uint32_t presentModeCount;
    result = vkGetPhysicalDeviceSurfacePresentModesKHR(device, m_surface, &presentModeCount, nullptr);
    if (result == VK_SUCCESS) {
        GOLOGW("vkGetPhysicalDeviceSurfacePresentModesKHR (count) completed successfully");
    } else {
        GOLOGE("vkGetPhysicalDeviceSurfacePresentModesKHR (count) failed with error: %d", result);
    }

    if (presentModeCount != 0) {
        details.presentModes.resize(presentModeCount);
        result = vkGetPhysicalDeviceSurfacePresentModesKHR(device, m_surface, &presentModeCount, details.presentModes.data());
        if (result == VK_SUCCESS) {
            GOLOGW("vkGetPhysicalDeviceSurfacePresentModesKHR (data) completed successfully");
        } else {
            GOLOGE("vkGetPhysicalDeviceSurfacePresentModesKHR (data) failed with error: %d", result);
        }
    }
    return details;
}

bool HelloVK::IsDeviceSuitable(VkPhysicalDevice device)
{
    QueueFamilyIndices indices = FindQueueFamilies(device);
    bool extensionsSupported = CheckDeviceExtensionSupport(device);
    bool swapChainAdequate = false;
    if (extensionsSupported) {
        SwapChainSupportDetails swapChainSupport = QuerySwapChainSupport(device);
        swapChainAdequate = !swapChainSupport.formats.empty() && !swapChainSupport.presentModes.empty();
    }

    return indices.isComplete() && extensionsSupported && swapChainAdequate;
}

void HelloVK::PickPhysicalDevice()
{
    uint32_t deviceCount = 0;
    VkResult result = vkEnumeratePhysicalDevices(m_instance, &deviceCount, nullptr);
    if (result == VK_SUCCESS) {
        GOLOGW("vkEnumeratePhysicalDevices (count) completed successfully");
    } else {
        GOLOGE("vkEnumeratePhysicalDevices (count) failed with error: %d", result);
        return;
    }

    if (deviceCount <= 0) {
        GOLOGE("failed to find GPUs with Vulkan support!");
        return;
    }

    std::vector<VkPhysicalDevice> devices(deviceCount);
    result = vkEnumeratePhysicalDevices(m_instance, &deviceCount, devices.data());
    if (result == VK_SUCCESS) {
        GOLOGW("vkEnumeratePhysicalDevices (data) completed successfully");
    } else {
        GOLOGE("vkEnumeratePhysicalDevices (data) failed with error: %d", result);
        return;
    }

    for (const auto &device : devices) {
        if (IsDeviceSuitable(device)) {
            m_physicalDevice = device;
            break;
        }
    }

    if (m_physicalDevice == VK_NULL_HANDLE) {
        GOLOGE("failed to find a suitable GPU!");
        return;
    }

    vkGetPhysicalDeviceFeatures(m_physicalDevice, &m_physicalDeviceFeatures);
    GOLOGW("vkGetPhysicalDeviceFeatures completed successfully");
    
    vkGetPhysicalDeviceProperties(m_physicalDevice, &m_physicalDeviceProperties);
    GOLOGW("vkGetPhysicalDeviceProperties completed successfully");
}
// END DEVICE SUITABILITY

void HelloVK::CreateLogicalDeviceAndQueue()
{
    QueueFamilyIndices indices = FindQueueFamilies(m_physicalDevice);
    std::vector<VkDeviceQueueCreateInfo> queueCreateInfos;
    std::set<uint32_t> uniqueQueueFamilies = { indices.graphicsFamily.value(), indices.presentFamily.value() };
    float queuePriority = 1.0F;
    for (uint32_t queueFamily : uniqueQueueFamilies) {
        VkDeviceQueueCreateInfo queueCreateInfo{};
        queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
        queueCreateInfo.queueFamilyIndex = queueFamily;
        queueCreateInfo.queueCount = 1;
        queueCreateInfo.pQueuePriorities = &queuePriority;
        queueCreateInfos.push_back(queueCreateInfo);
    }

    // 检查并启用Vulkan动态状态扩展
    std::vector<const char*> enabledExtensions(m_deviceExtensions.begin(), m_deviceExtensions.end());
    
    // 查询可用扩展
    uint32_t availableExtCount = 0;
    vkEnumerateDeviceExtensionProperties(m_physicalDevice, nullptr, &availableExtCount, nullptr);
    std::vector<VkExtensionProperties> availableExts(availableExtCount);
    vkEnumerateDeviceExtensionProperties(m_physicalDevice, nullptr, &availableExtCount, availableExts.data());
    
    // 尝试启用扩展动态状态扩展
    bool hasExtendedDynamicState = false;
    bool hasExtendedDynamicState2 = false;
    bool hasExtendedDynamicState3 = false;
    
    for (const auto& ext : availableExts) {
        if (strcmp(ext.extensionName, VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME) == 0) {
            hasExtendedDynamicState = true;
        }
        if (strcmp(ext.extensionName, VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME) == 0) {
            hasExtendedDynamicState2 = true;
        }
        if (strcmp(ext.extensionName, VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME) == 0) {
            hasExtendedDynamicState3 = true;
        }
    }
    
    if (hasExtendedDynamicState) {
        enabledExtensions.push_back(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
        GOLOGI("Enabling VK_EXT_extended_dynamic_state (adds 13 dynamic state commands)");
    } else {
        GOLOGW("VK_EXT_extended_dynamic_state NOT available (expected on Vulkan 1.0/1.1 devices)");
    }
    
    if (hasExtendedDynamicState2) {
        enabledExtensions.push_back(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
        GOLOGI("Enabling VK_EXT_extended_dynamic_state_2 (adds more dynamic states)");
    }
    
    if (hasExtendedDynamicState3) {
        enabledExtensions.push_back(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
        GOLOGI("Enabling VK_EXT_extended_dynamic_state_3 (Vulkan 1.3 backport)");
    }

    VkDeviceCreateInfo createInfo{};
    VkPhysicalDeviceFeatures deviceFeatures{};
    
    // Vulkan 1.3 动态状态特性 (如果驱动支持)
    VkPhysicalDeviceExtendedDynamicStateFeaturesEXT extendedDynamicStateFeatures{};
    extendedDynamicStateFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT;
    extendedDynamicStateFeatures.pNext = nullptr;
    extendedDynamicStateFeatures.extendedDynamicState = VK_TRUE;
    
    VkPhysicalDeviceFloat16Int8FeaturesKHR float16Int8Features{};
    float16Int8Features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES_KHR;
    float16Int8Features.pNext = hasExtendedDynamicState ? &extendedDynamicStateFeatures : nullptr;
    float16Int8Features.shaderFloat16 = VK_TRUE;
    float16Int8Features.shaderInt8 = VK_FALSE;
    createInfo.pNext = &float16Int8Features;

    deviceFeatures.samplerAnisotropy = m_physicalDeviceFeatures.samplerAnisotropy;
    deviceFeatures.shaderInt16 = VK_TRUE;
    deviceFeatures.fragmentStoresAndAtomics = VK_TRUE;

    createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
    createInfo.queueCreateInfoCount = static_cast<uint32_t>(queueCreateInfos.size());
    createInfo.pQueueCreateInfos = queueCreateInfos.data();
    createInfo.pEnabledFeatures = &deviceFeatures;
    createInfo.enabledExtensionCount = static_cast<uint32_t>(enabledExtensions.size());
    createInfo.ppEnabledExtensionNames = enabledExtensions.data();

    VkResult result = vkCreateDevice(m_physicalDevice, &createInfo, nullptr, &m_device);
    if (result == VK_SUCCESS) {
        GOLOGW("vkCreateDevice completed successfully");
    } else {
        GOLOGE("vkCreateDevice failed with error: %d", result);
        return;
    }

    vkGetDeviceQueue(m_device, indices.graphicsFamily.value(), 0, &m_graphicsQueue);
    GOLOGW("vkGetDeviceQueue (graphics) completed successfully");
    
    vkGetDeviceQueue(m_device, indices.presentFamily.value(), 0, &m_presentQueue);
    GOLOGW("vkGetDeviceQueue (present) completed successfully");
}

void HelloVK::EstablishDisplaySizeIdentity()
{
    VkSurfaceCapabilitiesKHR capabilities;
    VkResult result = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(m_physicalDevice, m_surface, &capabilities);
    if (result == VK_SUCCESS) {
        GOLOGW("vkGetPhysicalDeviceSurfaceCapabilitiesKHR completed successfully");
    } else {
        GOLOGE("vkGetPhysicalDeviceSurfaceCapabilitiesKHR failed with error: %d", result);
        return;
    }

    float ratio;
    if (capabilities.currentExtent.width < capabilities.currentExtent.height) {
        ratio = static_cast<float>(capabilities.currentExtent.width) / m_resolution;
    } else {
        ratio = static_cast<float>(capabilities.currentExtent.height) / m_resolution;
    }
    capabilities.currentExtent.width = static_cast<uint32_t>(capabilities.currentExtent.width / ratio);
    capabilities.currentExtent.height = static_cast<uint32_t>(capabilities.currentExtent.height / ratio);

    m_displaySizeIdentity = capabilities.currentExtent;
}

void HelloVK::ExecuteCreateSwapChain(VkSwapchainCreateInfoKHR &createInfo, uint32_t imageCount, VkFormat format)
{
    VkResult result = vkCreateSwapchainKHR(m_device, &createInfo, nullptr, &m_swapChain);
    if (result == VK_SUCCESS) {
        GOLOGW("vkCreateSwapchainKHR completed successfully");
    } else {
        GOLOGE("vkCreateSwapchainKHR failed with error: %d", result);
        return;
    }
    
    result = vkGetSwapchainImagesKHR(m_device, m_swapChain, &imageCount, nullptr);
    if (result == VK_SUCCESS) {
        GOLOGW("vkGetSwapchainImagesKHR (count) completed successfully");
    } else {
        GOLOGE("vkGetSwapchainImagesKHR (count) failed with error: %d", result);
    }
    
    m_swapChainImages.resize(imageCount);
    result = vkGetSwapchainImagesKHR(m_device, m_swapChain, &imageCount, m_swapChainImages.data());
    if (result == VK_SUCCESS) {
        GOLOGW("vkGetSwapchainImagesKHR (data) completed successfully");
    } else {
        GOLOGE("vkGetSwapchainImagesKHR (data) failed with error: %d", result);
    }

    for (uint32_t i = 0U; i < imageCount; ++i) {
        char label[256U];
        
        // 使用安全的 snprintf 替换 snprintf_s
        int iRet = std::snprintf(label, sizeof(label), "Swapchain image #%u", i);
        if (iRet < 0 || static_cast<size_t>(iRet) >= sizeof(label)) {
            // 格式化失败或缓冲区不足，使用默认标签
            std::strncpy(label, "Swapchain image", sizeof(label) - 1);
            label[sizeof(label) - 1] = '\0';  // 确保以null结尾
            GOLOGE("snprintf failed or buffer too small for swapchain image #%u", i);
        }
        
        OHTestApp::SetLabel(m_device, m_swapChainImages[i], VK_OBJECT_TYPE_IMAGE, label);
    }

    m_swapChainImageFormat = format;
    m_swapChainExtent = m_displaySizeIdentity;
    GOLOGI("create swapchain image count: %u", imageCount);
}

void HelloVK::CreateSwapChain()
{
    SwapChainSupportDetails swapChainSupport = QuerySwapChainSupport(m_physicalDevice);

    auto chooseSwapSurfaceFormat = [](const std::vector<VkSurfaceFormatKHR> &availableFormats) {
        for (const auto &availableFormat : availableFormats) {
            if (availableFormat.format == VK_FORMAT_B8G8R8A8_SRGB &&
                availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
                return availableFormat;
            }
        }

        return availableFormats[0];
    };

    VkSurfaceFormatKHR surfaceFormat = chooseSwapSurfaceFormat(swapChainSupport.formats);

    VkPresentModeKHR presentMode = VK_PRESENT_MODE_FIFO_KHR;

    uint32_t imageCount = swapChainSupport.capabilities.minImageCount + 1;
    if (swapChainSupport.capabilities.maxImageCount > 0 && imageCount > swapChainSupport.capabilities.maxImageCount) {
        imageCount = swapChainSupport.capabilities.maxImageCount;
    }
    GOLOGI("minSwapchain image count: %u request: %u", swapChainSupport.capabilities.minImageCount, imageCount);
    m_pretransformFlag = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;

    VkSwapchainCreateInfoKHR createInfo{};
    createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
    createInfo.surface = m_surface;
    createInfo.minImageCount = imageCount;
    createInfo.imageFormat = surfaceFormat.format;
    createInfo.imageColorSpace = surfaceFormat.colorSpace;
    createInfo.imageExtent = m_displaySizeIdentity;
    createInfo.imageArrayLayers = 1;

    createInfo.imageUsage =
        VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;

    createInfo.preTransform = m_pretransformFlag;

    QueueFamilyIndices indices = FindQueueFamilies(m_physicalDevice);
    uint32_t queueFamilyIndices[] = {indices.graphicsFamily.value(), indices.presentFamily.value()};

    if (indices.graphicsFamily != indices.presentFamily) {
        createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
        createInfo.queueFamilyIndexCount = 2U;
        createInfo.pQueueFamilyIndices = queueFamilyIndices;
    } else {
        createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
        createInfo.queueFamilyIndexCount = 0U;
        createInfo.pQueueFamilyIndices = nullptr;
    }

    createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR;
    createInfo.presentMode = presentMode;
    createInfo.clipped = VK_TRUE;
    createInfo.oldSwapchain = VK_NULL_HANDLE;

    ExecuteCreateSwapChain(createInfo, imageCount, surfaceFormat.format);
}

void HelloVK::CreateImageViews()
{
    m_swapChainImageViews.resize(m_swapChainImages.size());
    for (size_t i = 0; i < m_swapChainImages.size(); ++i) {
        VkImageViewCreateInfo createInfo{};
        createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
        createInfo.image = m_swapChainImages[i];
        createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
        createInfo.format = m_swapChainImageFormat;
        createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
        createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
        createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
        createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
        createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
        createInfo.subresourceRange.baseMipLevel = 0;
        createInfo.subresourceRange.levelCount = 1;
        createInfo.subresourceRange.baseArrayLayer = 0;
        createInfo.subresourceRange.layerCount = 1;
        
        VkResult result = vkCreateImageView(m_device, &createInfo, nullptr, &m_swapChainImageViews[i]);
        if (result == VK_SUCCESS) {
            GOLOGW("vkCreateImageView completed successfully for image %zu", i);
        } else {
            GOLOGE("vkCreateImageView failed with error: %d for image %zu", result, i);
        }
    }
}

void HelloVK::Acquire(VkSemaphore acquire)
{
    VkResult const result = vkAcquireNextImageKHR(m_device, m_swapChain, std::numeric_limits<uint64_t>::max(), acquire,
        VK_NULL_HANDLE, &m_imageIndex);
    if (result == VK_SUCCESS) {
        if (!s_loggedAcquireNextImage) {
            GOLOGW("vkAcquireNextImageKHR completed successfully");
            s_loggedAcquireNextImage = true;
        }
        return;
    }

    if (result != VK_ERROR_OUT_OF_DATE_KHR) {
        GOLOGE("Unexpected acquire result: %d", result);
        return;
    }

    RecreateSwapChain();

    VkResult retryResult = vkAcquireNextImageKHR(m_device, m_swapChain, std::numeric_limits<uint64_t>::max(), acquire, VK_NULL_HANDLE,
        &m_imageIndex);
    if (retryResult == VK_SUCCESS) {
        GOLOGW("vkAcquireNextImageKHR (retry) completed successfully");
    } else {
        GOLOGE("vkAcquireNextImageKHR (retry) failed with error: %d", retryResult);
    }
}

void HelloVK::Present(VkPresentInfoKHR const &presentInfo)
{
    VkResult const result = vkQueuePresentKHR(m_presentQueue, &presentInfo);
    if (result == VK_SUCCESS) {
        if (!s_loggedQueuePresent) {
            GOLOGW("vkQueuePresentKHR completed successfully");
            s_loggedQueuePresent = true;
        }
        return;
    }

    if (result == VK_SUBOPTIMAL_KHR) {
        GOLOGW("vkQueuePresentKHR returned VK_SUBOPTIMAL_KHR");
        m_orientationChanged = true;
        return;
    }

    if (result == VK_ERROR_OUT_OF_DATE_KHR) {
        GOLOGW("vkQueuePresentKHR returned VK_ERROR_OUT_OF_DATE_KHR");
        RecreateSwapChain();
        return;
    }

    GOLOGE("Unexpected present result: %d", result);
}

void HelloVK::FGInitDevice()
{
    OHTestApp::Device::Instance().Init(OHTestApp::Device::DeviceDescriptor()
        .Name("Device")
        .Instance(m_instance)
        .PhysicalDevice(m_physicalDevice)
        .LogicalDevice(m_device)
        .QueueFamilyIndex(0)
        .Queue(m_graphicsQueue));
}

void HelloVK::FGCreateColorResources()
{
    m_sceneColor.Init(OHTestApp::Image::ImageDescriptor()
        .Name("Scene Color")
        .Width(m_swapChainExtent.width)
        .Height(m_swapChainExtent.height)
        .Format(m_swapChainImageFormat)
        .Tile(VK_IMAGE_TILING_OPTIMAL)
        .MemProperties(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
        .InitialLayout(VK_IMAGE_LAYOUT_UNDEFINED)
        .Usage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT));

    m_sceneColor.GetNativeImageView();

    m_predictedColor.Init(OHTestApp::Image::ImageDescriptor()
        .Name("Predicted Color")
        .Width(m_swapChainExtent.width)
        .Height(m_swapChainExtent.height)
        .Format(m_swapChainImageFormat)
        .Tile(VK_IMAGE_TILING_OPTIMAL)
        .MemProperties(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
        .InitialLayout(VK_IMAGE_LAYOUT_UNDEFINED)
        .Usage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT));

    m_predictedColor.GetNativeImageView();
}

void HelloVK::FGDestroyColorResources()
{
    m_sceneColor.Destroy();
    m_predictedColor.Destroy();
}

void HelloVK::FGCreateDepthResources()
{
    VkFormat const format = OHTestApp::Device::Instance().FindDepthFormat();

    m_sceneDepthStencil.Init(OHTestApp::Image::ImageDescriptor()
        .Name("Scene Depth/Stencil")
        .Width(m_swapChainExtent.width)
        .Height(m_swapChainExtent.height)
        .Format(format)
        .Tile(VK_IMAGE_TILING_OPTIMAL)
        .MemProperties(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
        .InitialLayout(VK_IMAGE_LAYOUT_UNDEFINED)
        .Usage(VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT));

    m_sceneDepthStencil.GetNativeImageView(format, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT);
}

void HelloVK::CreateCommandPoolResources(const VkSemaphoreCreateInfo &semaphoreInfo,
    VkCommandPoolCreateInfo const &poolInfo, const VkFenceCreateInfo &fenceInfo,
    VkCommandBufferAllocateInfo &commandBufferAllocateInfo)
{
    for (uint32_t i = 0U; i < OHTestApp::FRAMES_IN_FLIGHT; ++i) {
        FrameInFlight &fif = m_framesInFlights[static_cast<size_t>(i)];
        
        VkResult result = vkCreateSemaphore(m_device, &semaphoreInfo, nullptr, &fif.acquire);
        if (result == VK_SUCCESS) {
            GOLOGW("vkCreateSemaphore (acquire) completed successfully for frame %u", i);
        } else {
            GOLOGE("vkCreateSemaphore (acquire) failed with error: %d for frame %u", result, i);
            return;
        }

        result = vkCreateCommandPool(m_device, &poolInfo, nullptr, &fif.commandPool);
        if (result == VK_SUCCESS) {
            GOLOGW("vkCreateCommandPool completed successfully for frame %u", i);
        } else {
            GOLOGE("vkCreateCommandPool failed with error: %d for frame %u", result, i);
            return;
        }

        commandBufferAllocateInfo.commandPool = fif.commandPool;
        result = vkAllocateCommandBuffers(m_device, &commandBufferAllocateInfo, &fif.commandBuffer);
        if (result == VK_SUCCESS) {
            GOLOGW("vkAllocateCommandBuffers completed successfully for frame %u", i);
        } else {
            GOLOGE("vkAllocateCommandBuffers failed with error: %d for frame %u", result, i);
            return;
        }

        char label[256U];
        
        // 使用安全的 snprintf 替换 snprintf_s
        int iRet = std::snprintf(label, sizeof(label), "FiF #%u", i);
        if (iRet < 0 || static_cast<size_t>(iRet) >= sizeof(label)) {
            // 格式化失败或缓冲区不足，使用默认标签
            std::strncpy(label, "FrameInFlight", sizeof(label) - 1);
            label[sizeof(label) - 1] = '\0';  // 确保以null结尾
            GOLOGE("snprintf failed or buffer too small for FiF #%u", i);
        }
        
        OHTestApp::SetLabel(m_device, fif.commandBuffer, VK_OBJECT_TYPE_COMMAND_BUFFER, label);

        result = vkCreateFence(m_device, &fenceInfo, nullptr, &fif.fence);
        if (result == VK_SUCCESS) {
            GOLOGW("vkCreateFence completed successfully for frame %u", i);
        } else {
            GOLOGE("vkCreateFence failed with error: %d for frame %u", result, i);
            return;
        }
    }
}

void HelloVK::FGCreateCommandPool()
{
    OHTestApp::CommandPool::Instance().Init(OHTestApp::CommandPool::CommandPoolDescriptor()
        .Name("CommandPool")
        .Device(m_device)
        .Flags(0U)
        .QueueFamilyIndex(OHTestApp::Device::Instance().GetQueueFamilyIndex())
        .Queue(OHTestApp::Device::Instance().GetNativeQueue()));

    constexpr VkSemaphoreCreateInfo semaphoreInfo {
        .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
        .pNext = nullptr,
        .flags = 0U
    };

    VkCommandPoolCreateInfo const poolInfo {
        .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
        .pNext = nullptr,
        .flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,
        .queueFamilyIndex = OHTestApp::Device::Instance().GetQueueFamilyIndex()
    };

    constexpr VkFenceCreateInfo fenceInfo {
        .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
        .pNext = nullptr,
        .flags = VK_FENCE_CREATE_SIGNALED_BIT
    };

    VkCommandBufferAllocateInfo commandBufferAllocateInfo {
        .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
        .pNext = nullptr,
        .commandPool = VK_NULL_HANDLE,
        .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
        .commandBufferCount = 1U
    };

    m_framesInFlights.clear();
    m_framesInFlights.resize(OHTestApp::FRAMES_IN_FLIGHT);
    m_writingCommandBufferIdx = 0U;

    CreateCommandPoolResources(semaphoreInfo, poolInfo, fenceInfo, commandBufferAllocateInfo);
}

void HelloVK::FGCreateSwapchainSyncObjects()
{
    size_t const count = m_swapChainImages.size();
    m_swapchainInfo.clear();
    m_swapchainInfo.resize(count);

    constexpr VkSemaphoreCreateInfo semaphoreInfo {
        .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
        .pNext = nullptr,
        .flags = 0U
    };

    for (size_t i = 0; i < count; ++i) {
        auto &info = m_swapchainInfo[i];
        VkResult result = vkCreateSemaphore(m_device, &semaphoreInfo, nullptr, &info.renderEnd);
        if (result == VK_SUCCESS) {
            GOLOGW("vkCreateSemaphore (renderEnd) completed successfully for swapchain image %zu", i);
        } else {
            GOLOGE("vkCreateSemaphore (renderEnd) failed with error: %d for swapchain image %zu", result, i);
            return;
        }
    }
}

void HelloVK::FGInitUIRenderer()
{
    OHTestApp::UIRenderer::UIRendererDescriptor desc{};
    desc.frameInFlightNum = OHTestApp::FRAMES_IN_FLIGHT;
    desc.frameBufferNum = m_swapChainImages.size();
    desc.canvasWidth = m_swapChainExtent.width;
    desc.canvasHeight = m_swapChainExtent.height;
    desc.colorFormat = m_swapChainImageFormat;

    for (auto &item : m_swapChainImageViews) {
        desc.colorImageViews.push_back(item);
    }

    OHTestApp::UIRenderer &renderer = OHTestApp::UIRenderer::Instance();
    renderer.Init(desc);

    m_sceneColorBackground = renderer.MakeBackground(m_sceneColor);
    m_predictedColorBackground = renderer.MakeBackground(m_predictedColor);
}

void HelloVK::FGInitMainSceneRenderer()
{
    OHTestApp::MainSceneRenderer &sceneRenderer = OHTestApp::MainSceneRenderer::Instance();

    sceneRenderer.Init(OHTestApp::MainSceneRenderer::MainSceneRendererDescriptor {
        .frameInFlightNum = OHTestApp::FRAMES_IN_FLIGHT,
        .frameBufferNum = OHTestApp::FRAMES_IN_FLIGHT,
        .frameBufferWidth = m_swapChainExtent.width,
        .frameBufferHeight = m_swapChainExtent.height,
        .colorFormat = m_sceneColor.GetFormat(),
        .depthStencilFormat = m_sceneDepthStencil.GetFormat()
    });

    VkImageView const attachments[] = {m_sceneColor.GetNativeImageView(), m_sceneDepthStencil.GetNativeImageView()};

    VkFramebufferCreateInfo framebufferInfo {
        .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
        .pNext = nullptr,
        .flags = 0U,
        .renderPass = sceneRenderer.GetRenderPass(),
        .attachmentCount = static_cast<uint32_t>(std::size(attachments)),
        .pAttachments = attachments,
        .width = m_swapChainExtent.width,
        .height = m_swapChainExtent.height,
        .layers = 1U
    };

    VkResult result = vkCreateFramebuffer(m_device, &framebufferInfo, nullptr, &m_sceneFramebuffer);
    if (result == VK_SUCCESS) {
        GOLOGW("vkCreateFramebuffer completed successfully");
    } else {
        GOLOGE("vkCreateFramebuffer failed with error: %d", result);
    }
}

void HelloVK::FGDestroyUIRenderer()
{
    OHTestApp::UIRenderer::Instance().Destroy();
}

void HelloVK::FGDestroyMainSceneRenderer()
{
    OHTestApp::MainSceneRenderer::Instance().Destroy();
}

void HelloVK::RenderAndUpdateCameraInfo(OHTestApp::MainSceneRenderer &sceneRenderer, FrameInFlight *fif,
    uint8_t fifIndex)
{
    sceneRenderer.Render(fif->commandBuffer, m_sceneFramebuffer, static_cast<size_t>(fifIndex));

    m_viewProj = sceneRenderer.GetSceneViewProjMatrix();
    m_invViewProj = glm::inverse(sceneRenderer.GetSceneViewProjMatrix());
}

void HelloVK::FGBalancedInterRender()
{

    if (!m_window) {
        return;
    }

    if (m_orientationChanged) {
        OnOrientationChange();
    }

    auto const fifIndex = static_cast<uint8_t>(m_writingCommandBufferIdx);
    FrameInFlight *fif = &m_framesInFlights[m_writingCommandBufferIdx];
    UpdateWritingCommandBufferIdx();

    VkResult result = vkWaitForFences(m_device, 1U, &fif->fence, VK_TRUE, std::numeric_limits<uint64_t>::max());
    if (result == VK_SUCCESS) {
        if (!s_loggedWaitForFences) {
            GOLOGW("vkWaitForFences completed successfully");
            s_loggedWaitForFences = true;
        }
    } else {
        GOLOGE("vkWaitForFences failed with error: %d", result);
    }

    ResetStatus(fif);

    VkCommandBufferBeginInfo beginCB = CreateBeginInfo();
    result = vkBeginCommandBuffer(fif->commandBuffer, &beginCB);
    if (result == VK_SUCCESS) {
        if (!s_loggedBeginCommandBuffer) {
            GOLOGW("vkBeginCommandBuffer completed successfully");
            s_loggedBeginCommandBuffer = true;
        }
    } else {
        GOLOGE("vkBeginCommandBuffer failed with error: %d", result);
    }

    OHTestApp::MainSceneRenderer &sceneRenderer = OHTestApp::MainSceneRenderer::Instance();
    sceneRenderer.Update(static_cast<uint32_t>(fifIndex));

    OHTestApp::UIRenderer &uiRenderer = OHTestApp::UIRenderer::Instance();
    uiRenderer.Update(static_cast<uint32_t>(fifIndex));

    // 标准渲染流程：渲染场景 -> 绘制UI -> 显示
    RenderAndUpdateCameraInfo(sceneRenderer, fif, fifIndex);
    
    uiRenderer.Draw(fif->commandBuffer, m_imageIndex, static_cast<uint32_t>(fifIndex), m_sceneColorBackground);

    result = vkEndCommandBuffer(fif->commandBuffer);
    if (result == VK_SUCCESS) {
        if (!s_loggedEndCommandBuffer) {
            GOLOGW("vkEndCommandBuffer completed successfully");
            s_loggedEndCommandBuffer = true;
        }
    } else {
        GOLOGE("vkEndCommandBuffer failed with error: %d", result);
    }

    InterRealFrameDisplay(fif);
}

VkSubmitInfo HelloVK::CreateSubmitInfo(FrameInFlight *fif, const VkPipelineStageFlags &waitStage)
{
    VkSubmitInfo submitInfo{};
    submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
    submitInfo.waitSemaphoreCount = 1U;
    submitInfo.pWaitSemaphores = &fif->acquire;
    submitInfo.pWaitDstStageMask = &waitStage;
    submitInfo.commandBufferCount = 1U;
    submitInfo.pCommandBuffers = &fif->commandBuffer;
    submitInfo.signalSemaphoreCount = 1U;
    submitInfo.pSignalSemaphores = &m_swapchainInfo[m_imageIndex].renderEnd;
    return submitInfo;
}

VkPresentInfoKHR HelloVK::CreatePresentInfo(VkResult &presentResult)
{
    VkPresentInfoKHR presentInfo{};
    presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
    presentInfo.waitSemaphoreCount = 1U;
    presentInfo.pWaitSemaphores = &m_swapchainInfo[m_imageIndex].renderEnd;
    presentInfo.swapchainCount = 1U;
    presentInfo.pSwapchains = &m_swapChain;
    presentInfo.pImageIndices = &m_imageIndex;
    presentInfo.pResults = &presentResult;
    return presentInfo;
}

void HelloVK::InterRealFrameDisplay(FrameInFlight *fif)
{
    // 标准Vulkan显示流程
    constexpr VkPipelineStageFlags waitStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
    
    VkSubmitInfo const submitInfo = CreateSubmitInfo(fif, waitStage);
    VkResult result = vkQueueSubmit(m_graphicsQueue, 1U, &submitInfo, fif->fence);
    if (result == VK_SUCCESS) {
        if (!s_loggedQueueSubmit) {
            GOLOGW("vkQueueSubmit completed successfully");
            s_loggedQueueSubmit = true;
        }
    } else {
        GOLOGE("vkQueueSubmit failed with error: %d", result);
    }

    VkResult presentResult = VK_SUCCESS;
    VkPresentInfoKHR const presentInfo = CreatePresentInfo(presentResult);
    Present(presentInfo);
}

void HelloVK::UpdateWritingCommandBufferIdx()
{
    m_writingCommandBufferIdx = (m_writingCommandBufferIdx + 1U) % OHTestApp::FRAMES_IN_FLIGHT;
}

VkCommandBufferBeginInfo HelloVK::CreateBeginInfo()
{
    VkCommandBufferBeginInfo beginInfo{};
    beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
    beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
    return beginInfo;
}

void HelloVK::ResetStatus(FrameInFlight *fif)
{
    VkResult result = vkResetFences(m_device, 1U, &fif->fence);
    if (result == VK_SUCCESS) {
        if (!s_loggedResetFences) {
            GOLOGW("vkResetFences completed successfully");
            s_loggedResetFences = true;
        }
    } else {
        GOLOGE("vkResetFences failed with error: %d", result);
    }

    result = vkResetCommandPool(m_device, fif->commandPool, 0U);
    if (result == VK_SUCCESS) {
        if (!s_loggedResetCommandPool) {
            GOLOGW("vkResetCommandPool completed successfully");
            s_loggedResetCommandPool = true;
        }
    } else {
        GOLOGE("vkResetCommandPool failed with error: %d", result);
    }

    Acquire(fif->acquire);
}

void HelloVK::ResetStatus(FrameInFlight *fif, VkCommandBufferBeginInfo &beginCB)
{
    ResetStatus(fif);
    VkResult result = vkBeginCommandBuffer(fif->commandBuffer, &beginCB);
    if (result == VK_SUCCESS) {
        if (!s_loggedBeginCommandBuffer) {
            GOLOGW("vkBeginCommandBuffer completed successfully");
            s_loggedBeginCommandBuffer = true;
        }
    } else {
        GOLOGE("vkBeginCommandBuffer failed with error: %d", result);
    }
}

} // namespace vkt